xref: /openbsd/usr.sbin/nsd/rdata.c (revision a302926f)
162ac0c33Sjakob /*
262ac0c33Sjakob  * rdata.c -- RDATA conversion functions.
362ac0c33Sjakob  *
4dd5b221eSsthen  * Copyright (c) 2001-2006, NLnet Labs. All rights reserved.
562ac0c33Sjakob  *
662ac0c33Sjakob  * See LICENSE for the license.
762ac0c33Sjakob  *
862ac0c33Sjakob  */
962ac0c33Sjakob 
10d11a62c8Ssthen #include "config.h"
1162ac0c33Sjakob 
1262ac0c33Sjakob #include <sys/types.h>
1362ac0c33Sjakob #include <sys/socket.h>
1462ac0c33Sjakob #include <netinet/in.h>
1562ac0c33Sjakob #include <arpa/inet.h>
1662ac0c33Sjakob #include <ctype.h>
1762ac0c33Sjakob #include <netdb.h>
1862ac0c33Sjakob #include <stdlib.h>
1962ac0c33Sjakob #include <string.h>
2062ac0c33Sjakob #ifdef HAVE_STRINGS_H
2162ac0c33Sjakob #include <strings.h>
2262ac0c33Sjakob #endif
2362ac0c33Sjakob 
2462ac0c33Sjakob #include "rdata.h"
2562ac0c33Sjakob #include "zonec.h"
2662ac0c33Sjakob 
2762ac0c33Sjakob /* Taken from RFC 4398, section 2.1.  */
2862ac0c33Sjakob lookup_table_type dns_certificate_types[] = {
2962ac0c33Sjakob /*	0		Reserved */
3062ac0c33Sjakob 	{ 1, "PKIX" },	/* X.509 as per PKIX */
3162ac0c33Sjakob 	{ 2, "SPKI" },	/* SPKI cert */
3262ac0c33Sjakob 	{ 3, "PGP" },	/* OpenPGP packet */
3362ac0c33Sjakob 	{ 4, "IPKIX" },	/* The URL of an X.509 data object */
3462ac0c33Sjakob 	{ 5, "ISPKI" },	/* The URL of an SPKI certificate */
3562ac0c33Sjakob 	{ 6, "IPGP" },	/* The fingerprint and URL of an OpenPGP packet */
3662ac0c33Sjakob 	{ 7, "ACPKIX" },	/* Attribute Certificate */
3762ac0c33Sjakob 	{ 8, "IACPKIX" },	/* The URL of an Attribute Certificate */
3862ac0c33Sjakob 	{ 253, "URI" },	/* URI private */
3962ac0c33Sjakob 	{ 254, "OID" },	/* OID private */
4062ac0c33Sjakob /*	255 		Reserved */
4162ac0c33Sjakob /* 	256-65279	Available for IANA assignment */
4262ac0c33Sjakob /*	65280-65534	Experimental */
4362ac0c33Sjakob /*	65535		Reserved */
4462ac0c33Sjakob 	{ 0, NULL }
4562ac0c33Sjakob };
4662ac0c33Sjakob 
4762ac0c33Sjakob /* Taken from RFC 2535, section 7.  */
4862ac0c33Sjakob lookup_table_type dns_algorithms[] = {
4962ac0c33Sjakob 	{ 1, "RSAMD5" },	/* RFC 2537 */
5062ac0c33Sjakob 	{ 2, "DH" },		/* RFC 2539 */
5162ac0c33Sjakob 	{ 3, "DSA" },		/* RFC 2536 */
5262ac0c33Sjakob 	{ 4, "ECC" },
5362ac0c33Sjakob 	{ 5, "RSASHA1" },	/* RFC 3110 */
54d11a62c8Ssthen 	{ 6, "DSA-NSEC3-SHA1" },	/* RFC 5155 */
55d11a62c8Ssthen 	{ 7, "RSASHA1-NSEC3-SHA1" },	/* RFC 5155 */
56d11a62c8Ssthen 	{ 8, "RSASHA256" },		/* RFC 5702 */
57d11a62c8Ssthen 	{ 10, "RSASHA512" },		/* RFC 5702 */
58d11a62c8Ssthen 	{ 12, "ECC-GOST" },		/* RFC 5933 */
59d11a62c8Ssthen 	{ 13, "ECDSAP256SHA256" },	/* RFC 6605 */
60d11a62c8Ssthen 	{ 14, "ECDSAP384SHA384" },	/* RFC 6605 */
6162ac0c33Sjakob 	{ 252, "INDIRECT" },
6262ac0c33Sjakob 	{ 253, "PRIVATEDNS" },
6362ac0c33Sjakob 	{ 254, "PRIVATEOID" },
6462ac0c33Sjakob 	{ 0, NULL }
6562ac0c33Sjakob };
6662ac0c33Sjakob 
6762ac0c33Sjakob typedef int (*rdata_to_string_type)(buffer_type *output,
6862ac0c33Sjakob 				    rdata_atom_type rdata,
6962ac0c33Sjakob 				    rr_type *rr);
7062ac0c33Sjakob 
7162ac0c33Sjakob static int
7262ac0c33Sjakob rdata_dname_to_string(buffer_type *output, rdata_atom_type rdata,
7362ac0c33Sjakob 	rr_type* ATTR_UNUSED(rr))
7462ac0c33Sjakob {
7562ac0c33Sjakob 	buffer_printf(output,
7662ac0c33Sjakob 		      "%s",
7762ac0c33Sjakob 		      dname_to_string(domain_dname(rdata_atom_domain(rdata)),
7862ac0c33Sjakob 				      NULL));
7962ac0c33Sjakob 	return 1;
8062ac0c33Sjakob }
8162ac0c33Sjakob 
8262ac0c33Sjakob static int
8362ac0c33Sjakob rdata_dns_name_to_string(buffer_type *output, rdata_atom_type rdata,
8462ac0c33Sjakob 	rr_type* ATTR_UNUSED(rr))
8562ac0c33Sjakob {
8662ac0c33Sjakob 	const uint8_t *data = rdata_atom_data(rdata);
8762ac0c33Sjakob 	size_t offset = 0;
8862ac0c33Sjakob 	uint8_t length = data[offset];
8962ac0c33Sjakob 	size_t i;
9062ac0c33Sjakob 
9162ac0c33Sjakob 	while (length > 0)
9262ac0c33Sjakob 	{
9362ac0c33Sjakob 		if (offset) /* concat label */
9462ac0c33Sjakob 			buffer_printf(output, ".");
9562ac0c33Sjakob 
9662ac0c33Sjakob 		for (i = 1; i <= length; ++i) {
97d65f3523Sjakob 			uint8_t ch = data[i+offset];
98d65f3523Sjakob 
99d65f3523Sjakob 			if (ch=='.' || ch==';' || ch=='(' || ch==')' || ch=='\\') {
100d65f3523Sjakob 				buffer_printf(output, "\\%c", (char) ch);
101*a302926fSbrad 			} else if (!isgraph((int)(unsigned char) ch)) {
102d65f3523Sjakob 				buffer_printf(output, "\\%03u", (unsigned int) ch);
103*a302926fSbrad 			} else if (isprint((int)(unsigned char) ch)) {
104d65f3523Sjakob 				buffer_printf(output, "%c", (char) ch);
105d65f3523Sjakob 			} else {
106d65f3523Sjakob 				buffer_printf(output, "\\%03u", (unsigned int) ch);
107d65f3523Sjakob 			}
10862ac0c33Sjakob 		}
10962ac0c33Sjakob 		/* next label */
11062ac0c33Sjakob 		offset = offset+length+1;
11162ac0c33Sjakob 		length = data[offset];
11262ac0c33Sjakob 	}
11362ac0c33Sjakob 
11462ac0c33Sjakob 	/* root label */
11562ac0c33Sjakob 	buffer_printf(output, ".");
11662ac0c33Sjakob 	return 1;
11762ac0c33Sjakob }
11862ac0c33Sjakob 
11962ac0c33Sjakob static int
12062ac0c33Sjakob rdata_text_to_string(buffer_type *output, rdata_atom_type rdata,
12162ac0c33Sjakob 	rr_type* ATTR_UNUSED(rr))
12262ac0c33Sjakob {
12362ac0c33Sjakob 	const uint8_t *data = rdata_atom_data(rdata);
12462ac0c33Sjakob 	uint8_t length = data[0];
12562ac0c33Sjakob 	size_t i;
12662ac0c33Sjakob 
12762ac0c33Sjakob 	buffer_printf(output, "\"");
12862ac0c33Sjakob 	for (i = 1; i <= length; ++i) {
12962ac0c33Sjakob 		char ch = (char) data[i];
130*a302926fSbrad 		if (isprint((int)(unsigned char)ch)) {
13162ac0c33Sjakob 			if (ch == '"' || ch == '\\') {
13262ac0c33Sjakob 				buffer_printf(output, "\\");
13362ac0c33Sjakob 			}
13462ac0c33Sjakob 			buffer_printf(output, "%c", ch);
13562ac0c33Sjakob 		} else {
1365bcb494bSjakob 			buffer_printf(output, "\\%03u", (unsigned) data[i]);
13762ac0c33Sjakob 		}
13862ac0c33Sjakob 	}
13962ac0c33Sjakob 	buffer_printf(output, "\"");
14062ac0c33Sjakob 	return 1;
14162ac0c33Sjakob }
14262ac0c33Sjakob 
14362ac0c33Sjakob static int
144f72b2965Sjakob rdata_texts_to_string(buffer_type *output, rdata_atom_type rdata,
145f72b2965Sjakob 	rr_type* ATTR_UNUSED(rr))
146f72b2965Sjakob {
147f72b2965Sjakob 	uint16_t pos = 0;
148f72b2965Sjakob 	const uint8_t *data = rdata_atom_data(rdata);
149f72b2965Sjakob 	uint16_t length = rdata_atom_size(rdata);
150f72b2965Sjakob 	size_t i;
151f72b2965Sjakob 
152f72b2965Sjakob 	while (pos < length && pos + data[pos] < length) {
153f72b2965Sjakob 		buffer_printf(output, "\"");
154f72b2965Sjakob 		for (i = 1; i <= data[pos]; ++i) {
155f72b2965Sjakob 			char ch = (char) data[pos + i];
156*a302926fSbrad 			if (isprint((int)(unsigned char)ch)) {
157f72b2965Sjakob 				if (ch == '"' || ch == '\\') {
158f72b2965Sjakob 					buffer_printf(output, "\\");
159f72b2965Sjakob 				}
160f72b2965Sjakob 				buffer_printf(output, "%c", ch);
161f72b2965Sjakob 			} else {
1625bcb494bSjakob 				buffer_printf(output, "\\%03u", (unsigned) data[pos+i]);
163f72b2965Sjakob 			}
164f72b2965Sjakob 		}
165f72b2965Sjakob 		pos += data[pos]+1;
166f72b2965Sjakob 		buffer_printf(output, pos < length?"\" ":"\"");
167f72b2965Sjakob 	}
168f72b2965Sjakob 	return 1;
169f72b2965Sjakob }
170f72b2965Sjakob 
171f72b2965Sjakob static int
172*a302926fSbrad rdata_long_text_to_string(buffer_type *output, rdata_atom_type rdata,
173*a302926fSbrad 	rr_type* ATTR_UNUSED(rr))
174*a302926fSbrad {
175*a302926fSbrad 	const uint8_t *data = rdata_atom_data(rdata);
176*a302926fSbrad 	uint16_t length = rdata_atom_size(rdata);
177*a302926fSbrad 	size_t i;
178*a302926fSbrad 
179*a302926fSbrad 	buffer_printf(output, "\"");
180*a302926fSbrad 	for (i = 0; i < length; ++i) {
181*a302926fSbrad 		char ch = (char) data[i];
182*a302926fSbrad 		if (isprint((int)(unsigned char)ch)) {
183*a302926fSbrad 			if (ch == '"' || ch == '\\') {
184*a302926fSbrad 				buffer_printf(output, "\\");
185*a302926fSbrad 			}
186*a302926fSbrad 			buffer_printf(output, "%c", ch);
187*a302926fSbrad 		} else {
188*a302926fSbrad 			buffer_printf(output, "\\%03u", (unsigned) data[i]);
189*a302926fSbrad 		}
190*a302926fSbrad 	}
191*a302926fSbrad 	buffer_printf(output, "\"");
192*a302926fSbrad 	return 1;
193*a302926fSbrad }
194*a302926fSbrad 
195*a302926fSbrad static int
196*a302926fSbrad rdata_tag_to_string(buffer_type *output, rdata_atom_type rdata,
197*a302926fSbrad 	rr_type* ATTR_UNUSED(rr))
198*a302926fSbrad {
199*a302926fSbrad 	const uint8_t *data = rdata_atom_data(rdata);
200*a302926fSbrad 	uint8_t length = data[0];
201*a302926fSbrad 	size_t i;
202*a302926fSbrad 	for (i = 1; i <= length; ++i) {
203*a302926fSbrad 		char ch = (char) data[i];
204*a302926fSbrad 		if (isdigit((int)ch) || islower((int)ch))
205*a302926fSbrad 			buffer_printf(output, "%c", ch);
206*a302926fSbrad 		else	return 0;
207*a302926fSbrad 	}
208*a302926fSbrad 	return 1;
209*a302926fSbrad }
210*a302926fSbrad 
211*a302926fSbrad static int
21262ac0c33Sjakob rdata_byte_to_string(buffer_type *output, rdata_atom_type rdata,
21362ac0c33Sjakob 	rr_type* ATTR_UNUSED(rr))
21462ac0c33Sjakob {
21562ac0c33Sjakob 	uint8_t data = *rdata_atom_data(rdata);
21662ac0c33Sjakob 	buffer_printf(output, "%lu", (unsigned long) data);
21762ac0c33Sjakob 	return 1;
21862ac0c33Sjakob }
21962ac0c33Sjakob 
22062ac0c33Sjakob static int
22162ac0c33Sjakob rdata_short_to_string(buffer_type *output, rdata_atom_type rdata,
22262ac0c33Sjakob 	rr_type* ATTR_UNUSED(rr))
22362ac0c33Sjakob {
22462ac0c33Sjakob 	uint16_t data = read_uint16(rdata_atom_data(rdata));
22562ac0c33Sjakob 	buffer_printf(output, "%lu", (unsigned long) data);
22662ac0c33Sjakob 	return 1;
22762ac0c33Sjakob }
22862ac0c33Sjakob 
22962ac0c33Sjakob static int
23062ac0c33Sjakob rdata_long_to_string(buffer_type *output, rdata_atom_type rdata,
23162ac0c33Sjakob 	rr_type* ATTR_UNUSED(rr))
23262ac0c33Sjakob {
23362ac0c33Sjakob 	uint32_t data = read_uint32(rdata_atom_data(rdata));
23462ac0c33Sjakob 	buffer_printf(output, "%lu", (unsigned long) data);
23562ac0c33Sjakob 	return 1;
23662ac0c33Sjakob }
23762ac0c33Sjakob 
23862ac0c33Sjakob static int
23962ac0c33Sjakob rdata_a_to_string(buffer_type *output, rdata_atom_type rdata,
24062ac0c33Sjakob 	rr_type* ATTR_UNUSED(rr))
24162ac0c33Sjakob {
24262ac0c33Sjakob 	int result = 0;
24362ac0c33Sjakob 	char str[200];
24462ac0c33Sjakob 	if (inet_ntop(AF_INET, rdata_atom_data(rdata), str, sizeof(str))) {
24562ac0c33Sjakob 		buffer_printf(output, "%s", str);
24662ac0c33Sjakob 		result = 1;
24762ac0c33Sjakob 	}
24862ac0c33Sjakob 	return result;
24962ac0c33Sjakob }
25062ac0c33Sjakob 
25162ac0c33Sjakob static int
25262ac0c33Sjakob rdata_aaaa_to_string(buffer_type *output, rdata_atom_type rdata,
25362ac0c33Sjakob 	rr_type* ATTR_UNUSED(rr))
25462ac0c33Sjakob {
25562ac0c33Sjakob 	int result = 0;
25662ac0c33Sjakob 	char str[200];
25762ac0c33Sjakob 	if (inet_ntop(AF_INET6, rdata_atom_data(rdata), str, sizeof(str))) {
25862ac0c33Sjakob 		buffer_printf(output, "%s", str);
25962ac0c33Sjakob 		result = 1;
26062ac0c33Sjakob 	}
26162ac0c33Sjakob 	return result;
26262ac0c33Sjakob }
26362ac0c33Sjakob 
26462ac0c33Sjakob static int
26575343be4Ssthen rdata_ilnp64_to_string(buffer_type *output, rdata_atom_type rdata,
26675343be4Ssthen 	rr_type* ATTR_UNUSED(rr))
26775343be4Ssthen {
26875343be4Ssthen 	uint8_t* data = rdata_atom_data(rdata);
26975343be4Ssthen 	uint16_t a1 = read_uint16(data);
27075343be4Ssthen 	uint16_t a2 = read_uint16(data+2);
27175343be4Ssthen 	uint16_t a3 = read_uint16(data+4);
27275343be4Ssthen 	uint16_t a4 = read_uint16(data+6);
27375343be4Ssthen 
27475343be4Ssthen 	buffer_printf(output, "%.4x:%.4x:%.4x:%.4x", a1, a2, a3, a4);
27575343be4Ssthen 	return 1;
27675343be4Ssthen }
27775343be4Ssthen 
2789c620270Ssthen static int
2799c620270Ssthen rdata_eui48_to_string(buffer_type *output, rdata_atom_type rdata,
2809c620270Ssthen 	rr_type* ATTR_UNUSED(rr))
2819c620270Ssthen {
2829c620270Ssthen 	uint8_t* data = rdata_atom_data(rdata);
2839c620270Ssthen 	uint8_t a1 = data[0];
2849c620270Ssthen 	uint8_t a2 = data[1];
2859c620270Ssthen 	uint8_t a3 = data[2];
2869c620270Ssthen 	uint8_t a4 = data[3];
2879c620270Ssthen 	uint8_t a5 = data[4];
2889c620270Ssthen 	uint8_t a6 = data[5];
2899c620270Ssthen 
2909c620270Ssthen 	buffer_printf(output, "%.2x-%.2x-%.2x-%.2x-%.2x-%.2x",
2919c620270Ssthen 		a1, a2, a3, a4, a5, a6);
2929c620270Ssthen 	return 1;
2939c620270Ssthen }
2949c620270Ssthen 
2959c620270Ssthen static int
2969c620270Ssthen rdata_eui64_to_string(buffer_type *output, rdata_atom_type rdata,
2979c620270Ssthen 	rr_type* ATTR_UNUSED(rr))
2989c620270Ssthen {
2999c620270Ssthen 	uint8_t* data = rdata_atom_data(rdata);
3009c620270Ssthen 	uint8_t a1 = data[0];
3019c620270Ssthen 	uint8_t a2 = data[1];
3029c620270Ssthen 	uint8_t a3 = data[2];
3039c620270Ssthen 	uint8_t a4 = data[3];
3049c620270Ssthen 	uint8_t a5 = data[4];
3059c620270Ssthen 	uint8_t a6 = data[5];
3069c620270Ssthen 	uint8_t a7 = data[6];
3079c620270Ssthen 	uint8_t a8 = data[7];
3089c620270Ssthen 
3099c620270Ssthen 	buffer_printf(output, "%.2x-%.2x-%.2x-%.2x-%.2x-%.2x-%.2x-%.2x",
3109c620270Ssthen 		a1, a2, a3, a4, a5, a6, a7, a8);
3119c620270Ssthen 	return 1;
3129c620270Ssthen }
3139c620270Ssthen 
31475343be4Ssthen static int
31562ac0c33Sjakob rdata_rrtype_to_string(buffer_type *output, rdata_atom_type rdata,
31662ac0c33Sjakob 	rr_type* ATTR_UNUSED(rr))
31762ac0c33Sjakob {
31862ac0c33Sjakob 	uint16_t type = read_uint16(rdata_atom_data(rdata));
31962ac0c33Sjakob 	buffer_printf(output, "%s", rrtype_to_string(type));
32062ac0c33Sjakob 	return 1;
32162ac0c33Sjakob }
32262ac0c33Sjakob 
32362ac0c33Sjakob static int
32462ac0c33Sjakob rdata_algorithm_to_string(buffer_type *output, rdata_atom_type rdata,
32562ac0c33Sjakob 	rr_type* ATTR_UNUSED(rr))
32662ac0c33Sjakob {
32762ac0c33Sjakob 	uint8_t id = *rdata_atom_data(rdata);
32862ac0c33Sjakob 	buffer_printf(output, "%u", (unsigned) id);
32962ac0c33Sjakob 	return 1;
33062ac0c33Sjakob }
33162ac0c33Sjakob 
33262ac0c33Sjakob static int
33362ac0c33Sjakob rdata_certificate_type_to_string(buffer_type *output, rdata_atom_type rdata,
33462ac0c33Sjakob 	rr_type* ATTR_UNUSED(rr))
33562ac0c33Sjakob {
33662ac0c33Sjakob 	uint16_t id = read_uint16(rdata_atom_data(rdata));
33762ac0c33Sjakob 	lookup_table_type *type
33862ac0c33Sjakob 		= lookup_by_id(dns_certificate_types, id);
33962ac0c33Sjakob 	if (type) {
34062ac0c33Sjakob 		buffer_printf(output, "%s", type->name);
34162ac0c33Sjakob 	} else {
34262ac0c33Sjakob 		buffer_printf(output, "%u", (unsigned) id);
34362ac0c33Sjakob 	}
34462ac0c33Sjakob 	return 1;
34562ac0c33Sjakob }
34662ac0c33Sjakob 
34762ac0c33Sjakob static int
34862ac0c33Sjakob rdata_period_to_string(buffer_type *output, rdata_atom_type rdata,
34962ac0c33Sjakob 	rr_type* ATTR_UNUSED(rr))
35062ac0c33Sjakob {
35162ac0c33Sjakob 	uint32_t period = read_uint32(rdata_atom_data(rdata));
35262ac0c33Sjakob 	buffer_printf(output, "%lu", (unsigned long) period);
35362ac0c33Sjakob 	return 1;
35462ac0c33Sjakob }
35562ac0c33Sjakob 
35662ac0c33Sjakob static int
35762ac0c33Sjakob rdata_time_to_string(buffer_type *output, rdata_atom_type rdata,
35862ac0c33Sjakob 	rr_type* ATTR_UNUSED(rr))
35962ac0c33Sjakob {
36062ac0c33Sjakob 	int result = 0;
36162ac0c33Sjakob 	time_t time = (time_t) read_uint32(rdata_atom_data(rdata));
36262ac0c33Sjakob 	struct tm *tm = gmtime(&time);
36362ac0c33Sjakob 	char buf[15];
36462ac0c33Sjakob 	if (strftime(buf, sizeof(buf), "%Y%m%d%H%M%S", tm)) {
36562ac0c33Sjakob 		buffer_printf(output, "%s", buf);
36662ac0c33Sjakob 		result = 1;
36762ac0c33Sjakob 	}
36862ac0c33Sjakob 	return result;
36962ac0c33Sjakob }
37062ac0c33Sjakob 
37162ac0c33Sjakob static int
37262ac0c33Sjakob rdata_base32_to_string(buffer_type *output, rdata_atom_type rdata,
37362ac0c33Sjakob 	rr_type* ATTR_UNUSED(rr))
37462ac0c33Sjakob {
37562ac0c33Sjakob 	int length;
37662ac0c33Sjakob 	size_t size = rdata_atom_size(rdata);
37762ac0c33Sjakob 	if(size == 0) {
37862ac0c33Sjakob 		buffer_write(output, "-", 1);
37962ac0c33Sjakob 		return 1;
38062ac0c33Sjakob 	}
38162ac0c33Sjakob 	size -= 1; /* remove length byte from count */
38262ac0c33Sjakob 	buffer_reserve(output, size * 2 + 1);
38362ac0c33Sjakob 	length = b32_ntop(rdata_atom_data(rdata)+1, size,
38462ac0c33Sjakob 			  (char *) buffer_current(output), size * 2);
38562ac0c33Sjakob 	if (length > 0) {
38662ac0c33Sjakob 		buffer_skip(output, length);
38762ac0c33Sjakob 	}
38862ac0c33Sjakob 	return length != -1;
38962ac0c33Sjakob }
39062ac0c33Sjakob 
39162ac0c33Sjakob static int
39262ac0c33Sjakob rdata_base64_to_string(buffer_type *output, rdata_atom_type rdata,
39362ac0c33Sjakob 	rr_type* ATTR_UNUSED(rr))
39462ac0c33Sjakob {
39562ac0c33Sjakob 	int length;
39662ac0c33Sjakob 	size_t size = rdata_atom_size(rdata);
3975bcb494bSjakob 	if(size == 0)
3985bcb494bSjakob 		return 1;
39962ac0c33Sjakob 	buffer_reserve(output, size * 2 + 1);
40062ac0c33Sjakob 	length = b64_ntop(rdata_atom_data(rdata), size,
40162ac0c33Sjakob 			  (char *) buffer_current(output), size * 2);
40262ac0c33Sjakob 	if (length > 0) {
40362ac0c33Sjakob 		buffer_skip(output, length);
40462ac0c33Sjakob 	}
40562ac0c33Sjakob 	return length != -1;
40662ac0c33Sjakob }
40762ac0c33Sjakob 
40862ac0c33Sjakob static void
40962ac0c33Sjakob hex_to_string(buffer_type *output, const uint8_t *data, size_t size)
41062ac0c33Sjakob {
41162ac0c33Sjakob 	static const char hexdigits[] = {
41262ac0c33Sjakob 		'0', '1', '2', '3', '4', '5', '6', '7',
41362ac0c33Sjakob 		'8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
41462ac0c33Sjakob 	};
41562ac0c33Sjakob 	size_t i;
41662ac0c33Sjakob 
41762ac0c33Sjakob 	buffer_reserve(output, size * 2);
41862ac0c33Sjakob 	for (i = 0; i < size; ++i) {
41962ac0c33Sjakob 		uint8_t octet = *data++;
42062ac0c33Sjakob 		buffer_write_u8(output, hexdigits[octet >> 4]);
42162ac0c33Sjakob 		buffer_write_u8(output, hexdigits[octet & 0x0f]);
42262ac0c33Sjakob 	}
42362ac0c33Sjakob }
42462ac0c33Sjakob 
42562ac0c33Sjakob static int
42662ac0c33Sjakob rdata_hex_to_string(buffer_type *output, rdata_atom_type rdata,
42762ac0c33Sjakob 	rr_type* ATTR_UNUSED(rr))
42862ac0c33Sjakob {
42962ac0c33Sjakob 	hex_to_string(output, rdata_atom_data(rdata), rdata_atom_size(rdata));
43062ac0c33Sjakob 	return 1;
43162ac0c33Sjakob }
43262ac0c33Sjakob 
43362ac0c33Sjakob static int
43462ac0c33Sjakob rdata_hexlen_to_string(buffer_type *output, rdata_atom_type rdata,
43562ac0c33Sjakob 	rr_type* ATTR_UNUSED(rr))
43662ac0c33Sjakob {
43762ac0c33Sjakob 	if(rdata_atom_size(rdata) <= 1) {
43862ac0c33Sjakob 		/* NSEC3 salt hex can be empty */
43962ac0c33Sjakob 		buffer_printf(output, "-");
44062ac0c33Sjakob 		return 1;
44162ac0c33Sjakob 	}
44262ac0c33Sjakob 	hex_to_string(output, rdata_atom_data(rdata)+1, rdata_atom_size(rdata)-1);
44362ac0c33Sjakob 	return 1;
44462ac0c33Sjakob }
44562ac0c33Sjakob 
44662ac0c33Sjakob static int
44762ac0c33Sjakob rdata_nsap_to_string(buffer_type *output, rdata_atom_type rdata,
44862ac0c33Sjakob 	rr_type* ATTR_UNUSED(rr))
44962ac0c33Sjakob {
45062ac0c33Sjakob 	buffer_printf(output, "0x");
45162ac0c33Sjakob 	hex_to_string(output, rdata_atom_data(rdata), rdata_atom_size(rdata));
45262ac0c33Sjakob 	return 1;
45362ac0c33Sjakob }
45462ac0c33Sjakob 
45562ac0c33Sjakob static int
45662ac0c33Sjakob rdata_apl_to_string(buffer_type *output, rdata_atom_type rdata,
45762ac0c33Sjakob 	rr_type* ATTR_UNUSED(rr))
45862ac0c33Sjakob {
45962ac0c33Sjakob 	int result = 0;
46062ac0c33Sjakob 	buffer_type packet;
46162ac0c33Sjakob 
46262ac0c33Sjakob 	buffer_create_from(
46362ac0c33Sjakob 		&packet, rdata_atom_data(rdata), rdata_atom_size(rdata));
46462ac0c33Sjakob 
46562ac0c33Sjakob 	if (buffer_available(&packet, 4)) {
46662ac0c33Sjakob 		uint16_t address_family = buffer_read_u16(&packet);
46762ac0c33Sjakob 		uint8_t prefix = buffer_read_u8(&packet);
46862ac0c33Sjakob 		uint8_t length = buffer_read_u8(&packet);
46962ac0c33Sjakob 		int negated = length & APL_NEGATION_MASK;
47062ac0c33Sjakob 		int af = -1;
47162ac0c33Sjakob 
47262ac0c33Sjakob 		length &= APL_LENGTH_MASK;
47362ac0c33Sjakob 		switch (address_family) {
47462ac0c33Sjakob 		case 1: af = AF_INET; break;
47562ac0c33Sjakob 		case 2: af = AF_INET6; break;
47662ac0c33Sjakob 		}
47762ac0c33Sjakob 		if (af != -1 && buffer_available(&packet, length)) {
47862ac0c33Sjakob 			char text_address[1000];
47962ac0c33Sjakob 			uint8_t address[128];
48062ac0c33Sjakob 			memset(address, 0, sizeof(address));
48162ac0c33Sjakob 			buffer_read(&packet, address, length);
48262ac0c33Sjakob 			if (inet_ntop(af, address, text_address, sizeof(text_address))) {
48362ac0c33Sjakob 				buffer_printf(output, "%s%d:%s/%d",
48462ac0c33Sjakob 					      negated ? "!" : "",
48562ac0c33Sjakob 					      (int) address_family,
48662ac0c33Sjakob 					      text_address,
48762ac0c33Sjakob 					      (int) prefix);
48862ac0c33Sjakob 				result = 1;
48962ac0c33Sjakob 			}
49062ac0c33Sjakob 		}
49162ac0c33Sjakob 	}
49262ac0c33Sjakob 	return result;
49362ac0c33Sjakob }
49462ac0c33Sjakob 
49562ac0c33Sjakob static int
49662ac0c33Sjakob rdata_services_to_string(buffer_type *output, rdata_atom_type rdata,
49762ac0c33Sjakob 	rr_type* ATTR_UNUSED(rr))
49862ac0c33Sjakob {
49962ac0c33Sjakob 	int result = 0;
50062ac0c33Sjakob 	buffer_type packet;
50162ac0c33Sjakob 
50262ac0c33Sjakob 	buffer_create_from(
50362ac0c33Sjakob 		&packet, rdata_atom_data(rdata), rdata_atom_size(rdata));
50462ac0c33Sjakob 
50562ac0c33Sjakob 	if (buffer_available(&packet, 1)) {
50662ac0c33Sjakob 		uint8_t protocol_number = buffer_read_u8(&packet);
50762ac0c33Sjakob 		ssize_t bitmap_size = buffer_remaining(&packet);
50862ac0c33Sjakob 		uint8_t *bitmap = buffer_current(&packet);
50962ac0c33Sjakob 		struct protoent *proto = getprotobynumber(protocol_number);
51062ac0c33Sjakob 
51162ac0c33Sjakob 		if (proto) {
51262ac0c33Sjakob 			int i;
51362ac0c33Sjakob 
51462ac0c33Sjakob 			buffer_printf(output, "%s", proto->p_name);
51562ac0c33Sjakob 
51662ac0c33Sjakob 			for (i = 0; i < bitmap_size * 8; ++i) {
51762ac0c33Sjakob 				if (get_bit(bitmap, i)) {
51862ac0c33Sjakob 					struct servent *service = getservbyport((int)htons(i), proto->p_name);
51962ac0c33Sjakob 					if (service) {
52062ac0c33Sjakob 						buffer_printf(output, " %s", service->s_name);
52162ac0c33Sjakob 					} else {
52262ac0c33Sjakob 						buffer_printf(output, " %d", i);
52362ac0c33Sjakob 					}
52462ac0c33Sjakob 				}
52562ac0c33Sjakob 			}
52662ac0c33Sjakob 			buffer_skip(&packet, bitmap_size);
52762ac0c33Sjakob 			result = 1;
52862ac0c33Sjakob 		}
52962ac0c33Sjakob 	}
53062ac0c33Sjakob 	return result;
53162ac0c33Sjakob }
53262ac0c33Sjakob 
53362ac0c33Sjakob static int
53462ac0c33Sjakob rdata_ipsecgateway_to_string(buffer_type *output, rdata_atom_type rdata, rr_type* rr)
53562ac0c33Sjakob {
53662ac0c33Sjakob 	int gateway_type = rdata_atom_data(rr->rdatas[1])[0];
53762ac0c33Sjakob 	switch(gateway_type) {
53862ac0c33Sjakob 	case IPSECKEY_NOGATEWAY:
53962ac0c33Sjakob 		buffer_printf(output, ".");
54062ac0c33Sjakob 		break;
54162ac0c33Sjakob 	case IPSECKEY_IP4:
54262ac0c33Sjakob 		rdata_a_to_string(output, rdata, rr);
54362ac0c33Sjakob 		break;
54462ac0c33Sjakob 	case IPSECKEY_IP6:
54562ac0c33Sjakob 		rdata_aaaa_to_string(output, rdata, rr);
54662ac0c33Sjakob 		break;
54762ac0c33Sjakob 	case IPSECKEY_DNAME:
5485bcb494bSjakob 		{
5495bcb494bSjakob 			region_type* temp = region_create(xalloc, free);
5505bcb494bSjakob 			const dname_type* d = dname_make(temp,
5515bcb494bSjakob 				rdata_atom_data(rdata), 0);
5525bcb494bSjakob 			if(!d) {
5535bcb494bSjakob 				region_destroy(temp);
5545bcb494bSjakob 				return 0;
5555bcb494bSjakob 			}
5565bcb494bSjakob 			buffer_printf(output, "%s", dname_to_string(d, NULL));
5575bcb494bSjakob 			region_destroy(temp);
5585bcb494bSjakob 		}
55962ac0c33Sjakob 		break;
56062ac0c33Sjakob 	default:
56162ac0c33Sjakob 		return 0;
56262ac0c33Sjakob 	}
56362ac0c33Sjakob 	return 1;
56462ac0c33Sjakob }
56562ac0c33Sjakob 
56662ac0c33Sjakob static int
56762ac0c33Sjakob rdata_nxt_to_string(buffer_type *output, rdata_atom_type rdata,
56862ac0c33Sjakob 	rr_type* ATTR_UNUSED(rr))
56962ac0c33Sjakob {
57062ac0c33Sjakob 	size_t i;
57162ac0c33Sjakob 	uint8_t *bitmap = rdata_atom_data(rdata);
57262ac0c33Sjakob 	size_t bitmap_size = rdata_atom_size(rdata);
57362ac0c33Sjakob 
57462ac0c33Sjakob 	for (i = 0; i < bitmap_size * 8; ++i) {
57562ac0c33Sjakob 		if (get_bit(bitmap, i)) {
57662ac0c33Sjakob 			buffer_printf(output, "%s ", rrtype_to_string(i));
57762ac0c33Sjakob 		}
57862ac0c33Sjakob 	}
57962ac0c33Sjakob 
58062ac0c33Sjakob 	buffer_skip(output, -1);
58162ac0c33Sjakob 
58262ac0c33Sjakob 	return 1;
58362ac0c33Sjakob }
58462ac0c33Sjakob 
58562ac0c33Sjakob static int
58662ac0c33Sjakob rdata_nsec_to_string(buffer_type *output, rdata_atom_type rdata,
58762ac0c33Sjakob 	rr_type* ATTR_UNUSED(rr))
58862ac0c33Sjakob {
58962ac0c33Sjakob 	size_t saved_position = buffer_position(output);
59062ac0c33Sjakob 	buffer_type packet;
59162ac0c33Sjakob 	int insert_space = 0;
59262ac0c33Sjakob 
59362ac0c33Sjakob 	buffer_create_from(
59462ac0c33Sjakob 		&packet, rdata_atom_data(rdata), rdata_atom_size(rdata));
59562ac0c33Sjakob 
59662ac0c33Sjakob 	while (buffer_available(&packet, 2)) {
59762ac0c33Sjakob 		uint8_t window = buffer_read_u8(&packet);
59862ac0c33Sjakob 		uint8_t bitmap_size = buffer_read_u8(&packet);
59962ac0c33Sjakob 		uint8_t *bitmap = buffer_current(&packet);
60062ac0c33Sjakob 		int i;
60162ac0c33Sjakob 
60262ac0c33Sjakob 		if (!buffer_available(&packet, bitmap_size)) {
60362ac0c33Sjakob 			buffer_set_position(output, saved_position);
60462ac0c33Sjakob 			return 0;
60562ac0c33Sjakob 		}
60662ac0c33Sjakob 
60762ac0c33Sjakob 		for (i = 0; i < bitmap_size * 8; ++i) {
60862ac0c33Sjakob 			if (get_bit(bitmap, i)) {
60962ac0c33Sjakob 				buffer_printf(output,
61062ac0c33Sjakob 					      "%s%s",
61162ac0c33Sjakob 					      insert_space ? " " : "",
61262ac0c33Sjakob 					      rrtype_to_string(
61362ac0c33Sjakob 						      window * 256 + i));
61462ac0c33Sjakob 				insert_space = 1;
61562ac0c33Sjakob 			}
61662ac0c33Sjakob 		}
61762ac0c33Sjakob 		buffer_skip(&packet, bitmap_size);
61862ac0c33Sjakob 	}
61962ac0c33Sjakob 
62062ac0c33Sjakob 	return 1;
62162ac0c33Sjakob }
62262ac0c33Sjakob 
62362ac0c33Sjakob static int
62462ac0c33Sjakob rdata_loc_to_string(buffer_type *ATTR_UNUSED(output),
62562ac0c33Sjakob 		    rdata_atom_type ATTR_UNUSED(rdata),
62662ac0c33Sjakob 		    rr_type* ATTR_UNUSED(rr))
62762ac0c33Sjakob {
62862ac0c33Sjakob 	/*
62962ac0c33Sjakob 	 * Returning 0 forces the record to be printed in unknown
63062ac0c33Sjakob 	 * format.
63162ac0c33Sjakob 	 */
63262ac0c33Sjakob 	return 0;
63362ac0c33Sjakob }
63462ac0c33Sjakob 
63562ac0c33Sjakob static int
63662ac0c33Sjakob rdata_unknown_to_string(buffer_type *output, rdata_atom_type rdata,
63762ac0c33Sjakob 	rr_type* ATTR_UNUSED(rr))
63862ac0c33Sjakob {
63962ac0c33Sjakob  	uint16_t size = rdata_atom_size(rdata);
64062ac0c33Sjakob  	buffer_printf(output, "\\# %lu ", (unsigned long) size);
64162ac0c33Sjakob 	hex_to_string(output, rdata_atom_data(rdata), size);
64262ac0c33Sjakob 	return 1;
64362ac0c33Sjakob }
64462ac0c33Sjakob 
64562ac0c33Sjakob static rdata_to_string_type rdata_to_string_table[RDATA_ZF_UNKNOWN + 1] = {
64662ac0c33Sjakob 	rdata_dname_to_string,
64762ac0c33Sjakob 	rdata_dns_name_to_string,
64862ac0c33Sjakob 	rdata_text_to_string,
649f72b2965Sjakob 	rdata_texts_to_string,
65062ac0c33Sjakob 	rdata_byte_to_string,
65162ac0c33Sjakob 	rdata_short_to_string,
65262ac0c33Sjakob 	rdata_long_to_string,
65362ac0c33Sjakob 	rdata_a_to_string,
65462ac0c33Sjakob 	rdata_aaaa_to_string,
65562ac0c33Sjakob 	rdata_rrtype_to_string,
65662ac0c33Sjakob 	rdata_algorithm_to_string,
65762ac0c33Sjakob 	rdata_certificate_type_to_string,
65862ac0c33Sjakob 	rdata_period_to_string,
65962ac0c33Sjakob 	rdata_time_to_string,
66062ac0c33Sjakob 	rdata_base64_to_string,
66162ac0c33Sjakob 	rdata_base32_to_string,
66262ac0c33Sjakob 	rdata_hex_to_string,
66362ac0c33Sjakob 	rdata_hexlen_to_string,
66462ac0c33Sjakob 	rdata_nsap_to_string,
66562ac0c33Sjakob 	rdata_apl_to_string,
66662ac0c33Sjakob 	rdata_ipsecgateway_to_string,
66762ac0c33Sjakob 	rdata_services_to_string,
66862ac0c33Sjakob 	rdata_nxt_to_string,
66962ac0c33Sjakob 	rdata_nsec_to_string,
67062ac0c33Sjakob 	rdata_loc_to_string,
67175343be4Ssthen 	rdata_ilnp64_to_string,
6729c620270Ssthen 	rdata_eui48_to_string,
6739c620270Ssthen 	rdata_eui64_to_string,
674*a302926fSbrad 	rdata_long_text_to_string,
675*a302926fSbrad 	rdata_tag_to_string,
67662ac0c33Sjakob 	rdata_unknown_to_string
67762ac0c33Sjakob };
67862ac0c33Sjakob 
67962ac0c33Sjakob int
68062ac0c33Sjakob rdata_atom_to_string(buffer_type *output, rdata_zoneformat_type type,
68162ac0c33Sjakob 		     rdata_atom_type rdata, rr_type* record)
68262ac0c33Sjakob {
68362ac0c33Sjakob 	return rdata_to_string_table[type](output, rdata, record);
68462ac0c33Sjakob }
68562ac0c33Sjakob 
68662ac0c33Sjakob ssize_t
68762ac0c33Sjakob rdata_wireformat_to_rdata_atoms(region_type *region,
68862ac0c33Sjakob 				domain_table_type *owners,
68962ac0c33Sjakob 				uint16_t rrtype,
69062ac0c33Sjakob 				uint16_t data_size,
69162ac0c33Sjakob 				buffer_type *packet,
69262ac0c33Sjakob 				rdata_atom_type **rdatas)
69362ac0c33Sjakob {
69462ac0c33Sjakob 	size_t end = buffer_position(packet) + data_size;
695d65f3523Sjakob 	size_t i;
69662ac0c33Sjakob 	rdata_atom_type temp_rdatas[MAXRDATALEN];
69762ac0c33Sjakob 	rrtype_descriptor_type *descriptor = rrtype_descriptor_by_type(rrtype);
69862ac0c33Sjakob 	region_type *temp_region;
69962ac0c33Sjakob 
70062ac0c33Sjakob 	assert(descriptor->maximum <= MAXRDATALEN);
70162ac0c33Sjakob 
70262ac0c33Sjakob 	if (!buffer_available(packet, data_size)) {
70362ac0c33Sjakob 		return -1;
70462ac0c33Sjakob 	}
70562ac0c33Sjakob 
70662ac0c33Sjakob 	temp_region = region_create(xalloc, free);
70762ac0c33Sjakob 
70862ac0c33Sjakob 	for (i = 0; i < descriptor->maximum; ++i) {
70962ac0c33Sjakob 		int is_domain = 0;
71062ac0c33Sjakob 		int is_normalized = 0;
71162ac0c33Sjakob 		int is_wirestore = 0;
71262ac0c33Sjakob 		size_t length = 0;
71362ac0c33Sjakob 		int required = i < descriptor->minimum;
71462ac0c33Sjakob 
71562ac0c33Sjakob 		switch (rdata_atom_wireformat_type(rrtype, i)) {
71662ac0c33Sjakob 		case RDATA_WF_COMPRESSED_DNAME:
71762ac0c33Sjakob 		case RDATA_WF_UNCOMPRESSED_DNAME:
71862ac0c33Sjakob 			is_domain = 1;
71962ac0c33Sjakob 			is_normalized = 1;
72062ac0c33Sjakob 			break;
72162ac0c33Sjakob 		case RDATA_WF_LITERAL_DNAME:
72262ac0c33Sjakob 			is_domain = 1;
72362ac0c33Sjakob 			is_wirestore = 1;
72462ac0c33Sjakob 			break;
72562ac0c33Sjakob 		case RDATA_WF_BYTE:
72662ac0c33Sjakob 			length = sizeof(uint8_t);
72762ac0c33Sjakob 			break;
72862ac0c33Sjakob 		case RDATA_WF_SHORT:
72962ac0c33Sjakob 			length = sizeof(uint16_t);
73062ac0c33Sjakob 			break;
73162ac0c33Sjakob 		case RDATA_WF_LONG:
73262ac0c33Sjakob 			length = sizeof(uint32_t);
73362ac0c33Sjakob 			break;
734f72b2965Sjakob 		case RDATA_WF_TEXTS:
735*a302926fSbrad 		case RDATA_WF_LONG_TEXT:
736*a302926fSbrad 			length = end - buffer_position(packet);
737f72b2965Sjakob 			break;
73862ac0c33Sjakob 		case RDATA_WF_TEXT:
73962ac0c33Sjakob 		case RDATA_WF_BINARYWITHLENGTH:
74062ac0c33Sjakob 			/* Length is stored in the first byte.  */
74162ac0c33Sjakob 			length = 1;
74262ac0c33Sjakob 			if (buffer_position(packet) + length <= end) {
74362ac0c33Sjakob 				length += buffer_current(packet)[length - 1];
74462ac0c33Sjakob 			}
74562ac0c33Sjakob 			break;
74662ac0c33Sjakob 		case RDATA_WF_A:
74762ac0c33Sjakob 			length = sizeof(in_addr_t);
74862ac0c33Sjakob 			break;
74962ac0c33Sjakob 		case RDATA_WF_AAAA:
75062ac0c33Sjakob 			length = IP6ADDRLEN;
75162ac0c33Sjakob 			break;
75275343be4Ssthen 		case RDATA_WF_ILNP64:
75375343be4Ssthen 			length = IP6ADDRLEN/2;
75475343be4Ssthen 			break;
7559c620270Ssthen 		case RDATA_WF_EUI48:
7569c620270Ssthen 			length = EUI48ADDRLEN;
757*a302926fSbrad 			break;
7589c620270Ssthen 		case RDATA_WF_EUI64:
7599c620270Ssthen 			length = EUI64ADDRLEN;
7609c620270Ssthen 			break;
76162ac0c33Sjakob 		case RDATA_WF_BINARY:
76262ac0c33Sjakob 			/* Remaining RDATA is binary.  */
76362ac0c33Sjakob 			length = end - buffer_position(packet);
76462ac0c33Sjakob 			break;
76562ac0c33Sjakob 		case RDATA_WF_APL:
76662ac0c33Sjakob 			length = (sizeof(uint16_t)    /* address family */
76762ac0c33Sjakob 				  + sizeof(uint8_t)   /* prefix */
76862ac0c33Sjakob 				  + sizeof(uint8_t)); /* length */
76962ac0c33Sjakob 			if (buffer_position(packet) + length <= end) {
77062ac0c33Sjakob 				/* Mask out negation bit.  */
77162ac0c33Sjakob 				length += (buffer_current(packet)[length - 1]
77262ac0c33Sjakob 					   & APL_LENGTH_MASK);
77362ac0c33Sjakob 			}
77462ac0c33Sjakob 			break;
77562ac0c33Sjakob 		case RDATA_WF_IPSECGATEWAY:
77662ac0c33Sjakob 			switch(rdata_atom_data(temp_rdatas[1])[0]) /* gateway type */ {
77762ac0c33Sjakob 			default:
77862ac0c33Sjakob 			case IPSECKEY_NOGATEWAY:
77962ac0c33Sjakob 				length = 0;
78062ac0c33Sjakob 				break;
78162ac0c33Sjakob 			case IPSECKEY_IP4:
78262ac0c33Sjakob 				length = IP4ADDRLEN;
78362ac0c33Sjakob 				break;
78462ac0c33Sjakob 			case IPSECKEY_IP6:
78562ac0c33Sjakob 				length = IP6ADDRLEN;
78662ac0c33Sjakob 				break;
78762ac0c33Sjakob 			case IPSECKEY_DNAME:
78862ac0c33Sjakob 				is_domain = 1;
78962ac0c33Sjakob 				is_normalized = 1;
79062ac0c33Sjakob 				is_wirestore = 1;
79162ac0c33Sjakob 				break;
79262ac0c33Sjakob 			}
79362ac0c33Sjakob 			break;
79462ac0c33Sjakob 		}
79562ac0c33Sjakob 
79662ac0c33Sjakob 		if (is_domain) {
79762ac0c33Sjakob 			const dname_type *dname;
79862ac0c33Sjakob 
79962ac0c33Sjakob 			if (!required && buffer_position(packet) == end) {
80062ac0c33Sjakob 				break;
80162ac0c33Sjakob 			}
80262ac0c33Sjakob 
80362ac0c33Sjakob 			dname = dname_make_from_packet(
80462ac0c33Sjakob 				temp_region, packet, 1, is_normalized);
80562ac0c33Sjakob 			if (!dname || buffer_position(packet) > end) {
80662ac0c33Sjakob 				/* Error in domain name.  */
80762ac0c33Sjakob 				region_destroy(temp_region);
80862ac0c33Sjakob 				return -1;
80962ac0c33Sjakob 			}
81062ac0c33Sjakob 			if(is_wirestore) {
81162ac0c33Sjakob 				temp_rdatas[i].data = (uint16_t *) region_alloc(
81262ac0c33Sjakob                                 	region, sizeof(uint16_t) + dname->name_size);
81362ac0c33Sjakob 				temp_rdatas[i].data[0] = dname->name_size;
81462ac0c33Sjakob 				memcpy(temp_rdatas[i].data+1, dname_name(dname),
81562ac0c33Sjakob 					dname->name_size);
816dd5b221eSsthen 			} else {
81762ac0c33Sjakob 				temp_rdatas[i].domain
81862ac0c33Sjakob 					= domain_table_insert(owners, dname);
819dd5b221eSsthen 				temp_rdatas[i].domain->usage ++;
820dd5b221eSsthen 			}
82162ac0c33Sjakob 		} else {
82262ac0c33Sjakob 			if (buffer_position(packet) + length > end) {
82362ac0c33Sjakob 				if (required) {
82462ac0c33Sjakob 					/* Truncated RDATA.  */
82562ac0c33Sjakob 					region_destroy(temp_region);
82662ac0c33Sjakob 					return -1;
82762ac0c33Sjakob 				} else {
82862ac0c33Sjakob 					break;
82962ac0c33Sjakob 				}
83062ac0c33Sjakob 			}
8315bcb494bSjakob 			if (!required && buffer_position(packet) == end) {
8325bcb494bSjakob 				break;
8335bcb494bSjakob 			}
83462ac0c33Sjakob 
83562ac0c33Sjakob 			temp_rdatas[i].data = (uint16_t *) region_alloc(
83662ac0c33Sjakob 				region, sizeof(uint16_t) + length);
83762ac0c33Sjakob 			temp_rdatas[i].data[0] = length;
83862ac0c33Sjakob 			buffer_read(packet, temp_rdatas[i].data + 1, length);
83962ac0c33Sjakob 		}
84062ac0c33Sjakob 	}
84162ac0c33Sjakob 
84262ac0c33Sjakob 	if (buffer_position(packet) < end) {
84362ac0c33Sjakob 		/* Trailing garbage.  */
84462ac0c33Sjakob 		region_destroy(temp_region);
84562ac0c33Sjakob 		return -1;
84662ac0c33Sjakob 	}
84762ac0c33Sjakob 
84862ac0c33Sjakob 	*rdatas = (rdata_atom_type *) region_alloc_init(
84962ac0c33Sjakob 		region, temp_rdatas, i * sizeof(rdata_atom_type));
85062ac0c33Sjakob 	region_destroy(temp_region);
851d65f3523Sjakob 	return (ssize_t)i;
85262ac0c33Sjakob }
85362ac0c33Sjakob 
85462ac0c33Sjakob size_t
85562ac0c33Sjakob rdata_maximum_wireformat_size(rrtype_descriptor_type *descriptor,
85662ac0c33Sjakob 			      size_t rdata_count,
85762ac0c33Sjakob 			      rdata_atom_type *rdatas)
85862ac0c33Sjakob {
85962ac0c33Sjakob 	size_t result = 0;
86062ac0c33Sjakob 	size_t i;
86162ac0c33Sjakob 	for (i = 0; i < rdata_count; ++i) {
86262ac0c33Sjakob 		if (rdata_atom_is_domain(descriptor->type, i)) {
86362ac0c33Sjakob 			result += domain_dname(rdata_atom_domain(rdatas[i]))->name_size;
86462ac0c33Sjakob 		} else {
86562ac0c33Sjakob 			result += rdata_atom_size(rdatas[i]);
86662ac0c33Sjakob 		}
86762ac0c33Sjakob 	}
86862ac0c33Sjakob 	return result;
86962ac0c33Sjakob }
87062ac0c33Sjakob 
87162ac0c33Sjakob int
87262ac0c33Sjakob rdata_atoms_to_unknown_string(buffer_type *output,
87362ac0c33Sjakob 			      rrtype_descriptor_type *descriptor,
87462ac0c33Sjakob 			      size_t rdata_count,
87562ac0c33Sjakob 			      rdata_atom_type *rdatas)
87662ac0c33Sjakob {
87762ac0c33Sjakob 	size_t i;
87862ac0c33Sjakob 	size_t size =
87962ac0c33Sjakob 		rdata_maximum_wireformat_size(descriptor, rdata_count, rdatas);
88062ac0c33Sjakob 	buffer_printf(output, " \\# %lu ", (unsigned long) size);
88162ac0c33Sjakob 	for (i = 0; i < rdata_count; ++i) {
88262ac0c33Sjakob 		if (rdata_atom_is_domain(descriptor->type, i)) {
88362ac0c33Sjakob 			const dname_type *dname =
88462ac0c33Sjakob 				domain_dname(rdata_atom_domain(rdatas[i]));
88562ac0c33Sjakob 			hex_to_string(
88662ac0c33Sjakob 				output, dname_name(dname), dname->name_size);
88762ac0c33Sjakob 		} else {
88862ac0c33Sjakob 			hex_to_string(output, rdata_atom_data(rdatas[i]),
88962ac0c33Sjakob 				rdata_atom_size(rdatas[i]));
89062ac0c33Sjakob 		}
89162ac0c33Sjakob 	}
89262ac0c33Sjakob 	return 1;
89362ac0c33Sjakob }
89462ac0c33Sjakob 
89562ac0c33Sjakob int
89662ac0c33Sjakob print_rdata(buffer_type *output, rrtype_descriptor_type *descriptor,
89762ac0c33Sjakob 	    rr_type *record)
89862ac0c33Sjakob {
89962ac0c33Sjakob 	size_t i;
90062ac0c33Sjakob 	size_t saved_position = buffer_position(output);
90162ac0c33Sjakob 
90262ac0c33Sjakob 	for (i = 0; i < record->rdata_count; ++i) {
90362ac0c33Sjakob 		if (i == 0) {
90462ac0c33Sjakob 			buffer_printf(output, "\t");
90562ac0c33Sjakob 		} else if (descriptor->type == TYPE_SOA && i == 2) {
90662ac0c33Sjakob 			buffer_printf(output, " (\n\t\t");
90762ac0c33Sjakob 		} else {
90862ac0c33Sjakob 			buffer_printf(output, " ");
90962ac0c33Sjakob 		}
91062ac0c33Sjakob 		if (!rdata_atom_to_string(
91162ac0c33Sjakob 			    output,
91262ac0c33Sjakob 			    (rdata_zoneformat_type) descriptor->zoneformat[i],
91362ac0c33Sjakob 			    record->rdatas[i], record))
91462ac0c33Sjakob 		{
91562ac0c33Sjakob 			buffer_set_position(output, saved_position);
91662ac0c33Sjakob 			return 0;
91762ac0c33Sjakob 		}
91862ac0c33Sjakob 	}
91962ac0c33Sjakob 	if (descriptor->type == TYPE_SOA) {
92062ac0c33Sjakob 		buffer_printf(output, " )");
92162ac0c33Sjakob 	}
92262ac0c33Sjakob 
92362ac0c33Sjakob 	return 1;
92462ac0c33Sjakob }
92562ac0c33Sjakob 
92662ac0c33Sjakob 
927