xref: /openbsd-src/usr.sbin/nsd/rdata.c (revision 4c1e55dc91edd6e69ccc60ce855900fbc12cf34f)
1 /*
2  * rdata.c -- RDATA conversion functions.
3  *
4  * Copyright (c) 2001-2011, 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 	{ 252, "INDIRECT" },
62 	{ 253, "PRIVATEDNS" },
63 	{ 254, "PRIVATEOID" },
64 	{ 0, NULL }
65 };
66 
67 typedef int (*rdata_to_string_type)(buffer_type *output,
68 				    rdata_atom_type rdata,
69 				    rr_type *rr);
70 
71 static int
72 rdata_dname_to_string(buffer_type *output, rdata_atom_type rdata,
73 	rr_type* ATTR_UNUSED(rr))
74 {
75 	buffer_printf(output,
76 		      "%s",
77 		      dname_to_string(domain_dname(rdata_atom_domain(rdata)),
78 				      NULL));
79 	return 1;
80 }
81 
82 static int
83 rdata_dns_name_to_string(buffer_type *output, rdata_atom_type rdata,
84 	rr_type* ATTR_UNUSED(rr))
85 {
86 	const uint8_t *data = rdata_atom_data(rdata);
87 	size_t offset = 0;
88 	uint8_t length = data[offset];
89 	size_t i;
90 
91 	while (length > 0)
92 	{
93 		if (offset) /* concat label */
94 			buffer_printf(output, ".");
95 
96 		for (i = 1; i <= length; ++i) {
97 			uint8_t ch = data[i+offset];
98 
99 			if (ch=='.' || ch==';' || ch=='(' || ch==')' || ch=='\\') {
100 				buffer_printf(output, "\\%c", (char) ch);
101 			} else if (!isgraph((int) ch)) {
102 				buffer_printf(output, "\\%03u", (unsigned int) ch);
103 			} else if (isprint((int) ch)) {
104 				buffer_printf(output, "%c", (char) ch);
105 			} else {
106 				buffer_printf(output, "\\%03u", (unsigned int) ch);
107 			}
108 		}
109 		/* next label */
110 		offset = offset+length+1;
111 		length = data[offset];
112 	}
113 
114 	/* root label */
115 	buffer_printf(output, ".");
116 	return 1;
117 }
118 
119 static int
120 rdata_text_to_string(buffer_type *output, rdata_atom_type rdata,
121 	rr_type* ATTR_UNUSED(rr))
122 {
123 	const uint8_t *data = rdata_atom_data(rdata);
124 	uint8_t length = data[0];
125 	size_t i;
126 
127 	buffer_printf(output, "\"");
128 	for (i = 1; i <= length; ++i) {
129 		char ch = (char) data[i];
130 		if (isprint((int)ch)) {
131 			if (ch == '"' || ch == '\\') {
132 				buffer_printf(output, "\\");
133 			}
134 			buffer_printf(output, "%c", ch);
135 		} else {
136 			buffer_printf(output, "\\%03u", (unsigned) data[i]);
137 		}
138 	}
139 	buffer_printf(output, "\"");
140 	return 1;
141 }
142 
143 static int
144 rdata_texts_to_string(buffer_type *output, rdata_atom_type rdata,
145 	rr_type* ATTR_UNUSED(rr))
146 {
147 	uint16_t pos = 0;
148 	const uint8_t *data = rdata_atom_data(rdata);
149 	uint16_t length = rdata_atom_size(rdata);
150 	size_t i;
151 
152 	while (pos < length && pos + data[pos] < length) {
153 		buffer_printf(output, "\"");
154 		for (i = 1; i <= data[pos]; ++i) {
155 			char ch = (char) data[pos + i];
156 			if (isprint((int)ch)) {
157 				if (ch == '"' || ch == '\\') {
158 					buffer_printf(output, "\\");
159 				}
160 				buffer_printf(output, "%c", ch);
161 			} else {
162 				buffer_printf(output, "\\%03u", (unsigned) data[pos+i]);
163 			}
164 		}
165 		pos += data[pos]+1;
166 		buffer_printf(output, pos < length?"\" ":"\"");
167 	}
168 	return 1;
169 }
170 
171 static int
172 rdata_byte_to_string(buffer_type *output, rdata_atom_type rdata,
173 	rr_type* ATTR_UNUSED(rr))
174 {
175 	uint8_t data = *rdata_atom_data(rdata);
176 	buffer_printf(output, "%lu", (unsigned long) data);
177 	return 1;
178 }
179 
180 static int
181 rdata_short_to_string(buffer_type *output, rdata_atom_type rdata,
182 	rr_type* ATTR_UNUSED(rr))
183 {
184 	uint16_t data = read_uint16(rdata_atom_data(rdata));
185 	buffer_printf(output, "%lu", (unsigned long) data);
186 	return 1;
187 }
188 
189 static int
190 rdata_long_to_string(buffer_type *output, rdata_atom_type rdata,
191 	rr_type* ATTR_UNUSED(rr))
192 {
193 	uint32_t data = read_uint32(rdata_atom_data(rdata));
194 	buffer_printf(output, "%lu", (unsigned long) data);
195 	return 1;
196 }
197 
198 static int
199 rdata_a_to_string(buffer_type *output, rdata_atom_type rdata,
200 	rr_type* ATTR_UNUSED(rr))
201 {
202 	int result = 0;
203 	char str[200];
204 	if (inet_ntop(AF_INET, rdata_atom_data(rdata), str, sizeof(str))) {
205 		buffer_printf(output, "%s", str);
206 		result = 1;
207 	}
208 	return result;
209 }
210 
211 static int
212 rdata_aaaa_to_string(buffer_type *output, rdata_atom_type rdata,
213 	rr_type* ATTR_UNUSED(rr))
214 {
215 	int result = 0;
216 	char str[200];
217 	if (inet_ntop(AF_INET6, rdata_atom_data(rdata), str, sizeof(str))) {
218 		buffer_printf(output, "%s", str);
219 		result = 1;
220 	}
221 	return result;
222 }
223 
224 static int
225 rdata_rrtype_to_string(buffer_type *output, rdata_atom_type rdata,
226 	rr_type* ATTR_UNUSED(rr))
227 {
228 	uint16_t type = read_uint16(rdata_atom_data(rdata));
229 	buffer_printf(output, "%s", rrtype_to_string(type));
230 	return 1;
231 }
232 
233 static int
234 rdata_algorithm_to_string(buffer_type *output, rdata_atom_type rdata,
235 	rr_type* ATTR_UNUSED(rr))
236 {
237 	uint8_t id = *rdata_atom_data(rdata);
238 	buffer_printf(output, "%u", (unsigned) id);
239 	return 1;
240 }
241 
242 static int
243 rdata_certificate_type_to_string(buffer_type *output, rdata_atom_type rdata,
244 	rr_type* ATTR_UNUSED(rr))
245 {
246 	uint16_t id = read_uint16(rdata_atom_data(rdata));
247 	lookup_table_type *type
248 		= lookup_by_id(dns_certificate_types, id);
249 	if (type) {
250 		buffer_printf(output, "%s", type->name);
251 	} else {
252 		buffer_printf(output, "%u", (unsigned) id);
253 	}
254 	return 1;
255 }
256 
257 static int
258 rdata_period_to_string(buffer_type *output, rdata_atom_type rdata,
259 	rr_type* ATTR_UNUSED(rr))
260 {
261 	uint32_t period = read_uint32(rdata_atom_data(rdata));
262 	buffer_printf(output, "%lu", (unsigned long) period);
263 	return 1;
264 }
265 
266 static int
267 rdata_time_to_string(buffer_type *output, rdata_atom_type rdata,
268 	rr_type* ATTR_UNUSED(rr))
269 {
270 	int result = 0;
271 	time_t time = (time_t) read_uint32(rdata_atom_data(rdata));
272 	struct tm *tm = gmtime(&time);
273 	char buf[15];
274 	if (strftime(buf, sizeof(buf), "%Y%m%d%H%M%S", tm)) {
275 		buffer_printf(output, "%s", buf);
276 		result = 1;
277 	}
278 	return result;
279 }
280 
281 static int
282 rdata_base32_to_string(buffer_type *output, rdata_atom_type rdata,
283 	rr_type* ATTR_UNUSED(rr))
284 {
285 	int length;
286 	size_t size = rdata_atom_size(rdata);
287 	if(size == 0) {
288 		buffer_write(output, "-", 1);
289 		return 1;
290 	}
291 	size -= 1; /* remove length byte from count */
292 	buffer_reserve(output, size * 2 + 1);
293 	length = b32_ntop(rdata_atom_data(rdata)+1, size,
294 			  (char *) buffer_current(output), size * 2);
295 	if (length > 0) {
296 		buffer_skip(output, length);
297 	}
298 	return length != -1;
299 }
300 
301 static int
302 rdata_base64_to_string(buffer_type *output, rdata_atom_type rdata,
303 	rr_type* ATTR_UNUSED(rr))
304 {
305 	int length;
306 	size_t size = rdata_atom_size(rdata);
307 	if(size == 0)
308 		return 1;
309 	buffer_reserve(output, size * 2 + 1);
310 	length = b64_ntop(rdata_atom_data(rdata), size,
311 			  (char *) buffer_current(output), size * 2);
312 	if (length > 0) {
313 		buffer_skip(output, length);
314 	}
315 	return length != -1;
316 }
317 
318 static void
319 hex_to_string(buffer_type *output, const uint8_t *data, size_t size)
320 {
321 	static const char hexdigits[] = {
322 		'0', '1', '2', '3', '4', '5', '6', '7',
323 		'8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
324 	};
325 	size_t i;
326 
327 	buffer_reserve(output, size * 2);
328 	for (i = 0; i < size; ++i) {
329 		uint8_t octet = *data++;
330 		buffer_write_u8(output, hexdigits[octet >> 4]);
331 		buffer_write_u8(output, hexdigits[octet & 0x0f]);
332 	}
333 }
334 
335 static int
336 rdata_hex_to_string(buffer_type *output, rdata_atom_type rdata,
337 	rr_type* ATTR_UNUSED(rr))
338 {
339 	hex_to_string(output, rdata_atom_data(rdata), rdata_atom_size(rdata));
340 	return 1;
341 }
342 
343 static int
344 rdata_hexlen_to_string(buffer_type *output, rdata_atom_type rdata,
345 	rr_type* ATTR_UNUSED(rr))
346 {
347 	if(rdata_atom_size(rdata) <= 1) {
348 		/* NSEC3 salt hex can be empty */
349 		buffer_printf(output, "-");
350 		return 1;
351 	}
352 	hex_to_string(output, rdata_atom_data(rdata)+1, rdata_atom_size(rdata)-1);
353 	return 1;
354 }
355 
356 static int
357 rdata_nsap_to_string(buffer_type *output, rdata_atom_type rdata,
358 	rr_type* ATTR_UNUSED(rr))
359 {
360 	buffer_printf(output, "0x");
361 	hex_to_string(output, rdata_atom_data(rdata), rdata_atom_size(rdata));
362 	return 1;
363 }
364 
365 static int
366 rdata_apl_to_string(buffer_type *output, rdata_atom_type rdata,
367 	rr_type* ATTR_UNUSED(rr))
368 {
369 	int result = 0;
370 	buffer_type packet;
371 
372 	buffer_create_from(
373 		&packet, rdata_atom_data(rdata), rdata_atom_size(rdata));
374 
375 	if (buffer_available(&packet, 4)) {
376 		uint16_t address_family = buffer_read_u16(&packet);
377 		uint8_t prefix = buffer_read_u8(&packet);
378 		uint8_t length = buffer_read_u8(&packet);
379 		int negated = length & APL_NEGATION_MASK;
380 		int af = -1;
381 
382 		length &= APL_LENGTH_MASK;
383 		switch (address_family) {
384 		case 1: af = AF_INET; break;
385 		case 2: af = AF_INET6; break;
386 		}
387 		if (af != -1 && buffer_available(&packet, length)) {
388 			char text_address[1000];
389 			uint8_t address[128];
390 			memset(address, 0, sizeof(address));
391 			buffer_read(&packet, address, length);
392 			if (inet_ntop(af, address, text_address, sizeof(text_address))) {
393 				buffer_printf(output, "%s%d:%s/%d",
394 					      negated ? "!" : "",
395 					      (int) address_family,
396 					      text_address,
397 					      (int) prefix);
398 				result = 1;
399 			}
400 		}
401 	}
402 	return result;
403 }
404 
405 static int
406 rdata_services_to_string(buffer_type *output, rdata_atom_type rdata,
407 	rr_type* ATTR_UNUSED(rr))
408 {
409 	int result = 0;
410 	buffer_type packet;
411 
412 	buffer_create_from(
413 		&packet, rdata_atom_data(rdata), rdata_atom_size(rdata));
414 
415 	if (buffer_available(&packet, 1)) {
416 		uint8_t protocol_number = buffer_read_u8(&packet);
417 		ssize_t bitmap_size = buffer_remaining(&packet);
418 		uint8_t *bitmap = buffer_current(&packet);
419 		struct protoent *proto = getprotobynumber(protocol_number);
420 
421 		if (proto) {
422 			int i;
423 
424 			buffer_printf(output, "%s", proto->p_name);
425 
426 			for (i = 0; i < bitmap_size * 8; ++i) {
427 				if (get_bit(bitmap, i)) {
428 					struct servent *service = getservbyport((int)htons(i), proto->p_name);
429 					if (service) {
430 						buffer_printf(output, " %s", service->s_name);
431 					} else {
432 						buffer_printf(output, " %d", i);
433 					}
434 				}
435 			}
436 			buffer_skip(&packet, bitmap_size);
437 			result = 1;
438 		}
439 	}
440 	return result;
441 }
442 
443 static int
444 rdata_ipsecgateway_to_string(buffer_type *output, rdata_atom_type rdata, rr_type* rr)
445 {
446 	int gateway_type = rdata_atom_data(rr->rdatas[1])[0];
447 	switch(gateway_type) {
448 	case IPSECKEY_NOGATEWAY:
449 		buffer_printf(output, ".");
450 		break;
451 	case IPSECKEY_IP4:
452 		rdata_a_to_string(output, rdata, rr);
453 		break;
454 	case IPSECKEY_IP6:
455 		rdata_aaaa_to_string(output, rdata, rr);
456 		break;
457 	case IPSECKEY_DNAME:
458 		{
459 			region_type* temp = region_create(xalloc, free);
460 			const dname_type* d = dname_make(temp,
461 				rdata_atom_data(rdata), 0);
462 			if(!d) {
463 				region_destroy(temp);
464 				return 0;
465 			}
466 			buffer_printf(output, "%s", dname_to_string(d, NULL));
467 			region_destroy(temp);
468 		}
469 		break;
470 	default:
471 		return 0;
472 	}
473 	return 1;
474 }
475 
476 static int
477 rdata_nxt_to_string(buffer_type *output, rdata_atom_type rdata,
478 	rr_type* ATTR_UNUSED(rr))
479 {
480 	size_t i;
481 	uint8_t *bitmap = rdata_atom_data(rdata);
482 	size_t bitmap_size = rdata_atom_size(rdata);
483 
484 	for (i = 0; i < bitmap_size * 8; ++i) {
485 		if (get_bit(bitmap, i)) {
486 			buffer_printf(output, "%s ", rrtype_to_string(i));
487 		}
488 	}
489 
490 	buffer_skip(output, -1);
491 
492 	return 1;
493 }
494 
495 static int
496 rdata_nsec_to_string(buffer_type *output, rdata_atom_type rdata,
497 	rr_type* ATTR_UNUSED(rr))
498 {
499 	size_t saved_position = buffer_position(output);
500 	buffer_type packet;
501 	int insert_space = 0;
502 
503 	buffer_create_from(
504 		&packet, rdata_atom_data(rdata), rdata_atom_size(rdata));
505 
506 	while (buffer_available(&packet, 2)) {
507 		uint8_t window = buffer_read_u8(&packet);
508 		uint8_t bitmap_size = buffer_read_u8(&packet);
509 		uint8_t *bitmap = buffer_current(&packet);
510 		int i;
511 
512 		if (!buffer_available(&packet, bitmap_size)) {
513 			buffer_set_position(output, saved_position);
514 			return 0;
515 		}
516 
517 		for (i = 0; i < bitmap_size * 8; ++i) {
518 			if (get_bit(bitmap, i)) {
519 				buffer_printf(output,
520 					      "%s%s",
521 					      insert_space ? " " : "",
522 					      rrtype_to_string(
523 						      window * 256 + i));
524 				insert_space = 1;
525 			}
526 		}
527 		buffer_skip(&packet, bitmap_size);
528 	}
529 
530 	return 1;
531 }
532 
533 static int
534 rdata_loc_to_string(buffer_type *ATTR_UNUSED(output),
535 		    rdata_atom_type ATTR_UNUSED(rdata),
536 		    rr_type* ATTR_UNUSED(rr))
537 {
538 	/*
539 	 * Returning 0 forces the record to be printed in unknown
540 	 * format.
541 	 */
542 	return 0;
543 }
544 
545 static int
546 rdata_unknown_to_string(buffer_type *output, rdata_atom_type rdata,
547 	rr_type* ATTR_UNUSED(rr))
548 {
549  	uint16_t size = rdata_atom_size(rdata);
550  	buffer_printf(output, "\\# %lu ", (unsigned long) size);
551 	hex_to_string(output, rdata_atom_data(rdata), size);
552 	return 1;
553 }
554 
555 static rdata_to_string_type rdata_to_string_table[RDATA_ZF_UNKNOWN + 1] = {
556 	rdata_dname_to_string,
557 	rdata_dns_name_to_string,
558 	rdata_text_to_string,
559 	rdata_texts_to_string,
560 	rdata_byte_to_string,
561 	rdata_short_to_string,
562 	rdata_long_to_string,
563 	rdata_a_to_string,
564 	rdata_aaaa_to_string,
565 	rdata_rrtype_to_string,
566 	rdata_algorithm_to_string,
567 	rdata_certificate_type_to_string,
568 	rdata_period_to_string,
569 	rdata_time_to_string,
570 	rdata_base64_to_string,
571 	rdata_base32_to_string,
572 	rdata_hex_to_string,
573 	rdata_hexlen_to_string,
574 	rdata_nsap_to_string,
575 	rdata_apl_to_string,
576 	rdata_ipsecgateway_to_string,
577 	rdata_services_to_string,
578 	rdata_nxt_to_string,
579 	rdata_nsec_to_string,
580 	rdata_loc_to_string,
581 	rdata_unknown_to_string
582 };
583 
584 int
585 rdata_atom_to_string(buffer_type *output, rdata_zoneformat_type type,
586 		     rdata_atom_type rdata, rr_type* record)
587 {
588 	return rdata_to_string_table[type](output, rdata, record);
589 }
590 
591 ssize_t
592 rdata_wireformat_to_rdata_atoms(region_type *region,
593 				domain_table_type *owners,
594 				uint16_t rrtype,
595 				uint16_t data_size,
596 				buffer_type *packet,
597 				rdata_atom_type **rdatas)
598 {
599 	size_t end = buffer_position(packet) + data_size;
600 	size_t i;
601 	rdata_atom_type temp_rdatas[MAXRDATALEN];
602 	rrtype_descriptor_type *descriptor = rrtype_descriptor_by_type(rrtype);
603 	region_type *temp_region;
604 
605 	assert(descriptor->maximum <= MAXRDATALEN);
606 
607 	if (!buffer_available(packet, data_size)) {
608 		return -1;
609 	}
610 
611 	temp_region = region_create(xalloc, free);
612 
613 	for (i = 0; i < descriptor->maximum; ++i) {
614 		int is_domain = 0;
615 		int is_normalized = 0;
616 		int is_wirestore = 0;
617 		size_t length = 0;
618 		int required = i < descriptor->minimum;
619 
620 		switch (rdata_atom_wireformat_type(rrtype, i)) {
621 		case RDATA_WF_COMPRESSED_DNAME:
622 		case RDATA_WF_UNCOMPRESSED_DNAME:
623 			is_domain = 1;
624 			is_normalized = 1;
625 			break;
626 		case RDATA_WF_LITERAL_DNAME:
627 			is_domain = 1;
628 			is_wirestore = 1;
629 			break;
630 		case RDATA_WF_BYTE:
631 			length = sizeof(uint8_t);
632 			break;
633 		case RDATA_WF_SHORT:
634 			length = sizeof(uint16_t);
635 			break;
636 		case RDATA_WF_LONG:
637 			length = sizeof(uint32_t);
638 			break;
639 		case RDATA_WF_TEXTS:
640 			length = data_size;
641 			break;
642 		case RDATA_WF_TEXT:
643 		case RDATA_WF_BINARYWITHLENGTH:
644 			/* Length is stored in the first byte.  */
645 			length = 1;
646 			if (buffer_position(packet) + length <= end) {
647 				length += buffer_current(packet)[length - 1];
648 			}
649 			break;
650 		case RDATA_WF_A:
651 			length = sizeof(in_addr_t);
652 			break;
653 		case RDATA_WF_AAAA:
654 			length = IP6ADDRLEN;
655 			break;
656 		case RDATA_WF_BINARY:
657 			/* Remaining RDATA is binary.  */
658 			length = end - buffer_position(packet);
659 			break;
660 		case RDATA_WF_APL:
661 			length = (sizeof(uint16_t)    /* address family */
662 				  + sizeof(uint8_t)   /* prefix */
663 				  + sizeof(uint8_t)); /* length */
664 			if (buffer_position(packet) + length <= end) {
665 				/* Mask out negation bit.  */
666 				length += (buffer_current(packet)[length - 1]
667 					   & APL_LENGTH_MASK);
668 			}
669 			break;
670 		case RDATA_WF_IPSECGATEWAY:
671 			switch(rdata_atom_data(temp_rdatas[1])[0]) /* gateway type */ {
672 			default:
673 			case IPSECKEY_NOGATEWAY:
674 				length = 0;
675 				break;
676 			case IPSECKEY_IP4:
677 				length = IP4ADDRLEN;
678 				break;
679 			case IPSECKEY_IP6:
680 				length = IP6ADDRLEN;
681 				break;
682 			case IPSECKEY_DNAME:
683 				is_domain = 1;
684 				is_normalized = 1;
685 				is_wirestore = 1;
686 				break;
687 			}
688 			break;
689 		}
690 
691 		if (is_domain) {
692 			const dname_type *dname;
693 
694 			if (!required && buffer_position(packet) == end) {
695 				break;
696 			}
697 
698 			dname = dname_make_from_packet(
699 				temp_region, packet, 1, is_normalized);
700 			if (!dname || buffer_position(packet) > end) {
701 				/* Error in domain name.  */
702 				region_destroy(temp_region);
703 				return -1;
704 			}
705 			if(is_wirestore) {
706 				temp_rdatas[i].data = (uint16_t *) region_alloc(
707                                 	region, sizeof(uint16_t) + dname->name_size);
708 				temp_rdatas[i].data[0] = dname->name_size;
709 				memcpy(temp_rdatas[i].data+1, dname_name(dname),
710 					dname->name_size);
711 			} else
712 				temp_rdatas[i].domain
713 					= domain_table_insert(owners, dname);
714 		} else {
715 			if (buffer_position(packet) + length > end) {
716 				if (required) {
717 					/* Truncated RDATA.  */
718 					region_destroy(temp_region);
719 					return -1;
720 				} else {
721 					break;
722 				}
723 			}
724 			if (!required && buffer_position(packet) == end) {
725 				break;
726 			}
727 
728 			temp_rdatas[i].data = (uint16_t *) region_alloc(
729 				region, sizeof(uint16_t) + length);
730 			temp_rdatas[i].data[0] = length;
731 			buffer_read(packet, temp_rdatas[i].data + 1, length);
732 		}
733 	}
734 
735 	if (buffer_position(packet) < end) {
736 		/* Trailing garbage.  */
737 		region_destroy(temp_region);
738 		return -1;
739 	}
740 
741 	*rdatas = (rdata_atom_type *) region_alloc_init(
742 		region, temp_rdatas, i * sizeof(rdata_atom_type));
743 	region_destroy(temp_region);
744 	return (ssize_t)i;
745 }
746 
747 size_t
748 rdata_maximum_wireformat_size(rrtype_descriptor_type *descriptor,
749 			      size_t rdata_count,
750 			      rdata_atom_type *rdatas)
751 {
752 	size_t result = 0;
753 	size_t i;
754 	for (i = 0; i < rdata_count; ++i) {
755 		if (rdata_atom_is_domain(descriptor->type, i)) {
756 			result += domain_dname(rdata_atom_domain(rdatas[i]))->name_size;
757 		} else {
758 			result += rdata_atom_size(rdatas[i]);
759 		}
760 	}
761 	return result;
762 }
763 
764 int
765 rdata_atoms_to_unknown_string(buffer_type *output,
766 			      rrtype_descriptor_type *descriptor,
767 			      size_t rdata_count,
768 			      rdata_atom_type *rdatas)
769 {
770 	size_t i;
771 	size_t size =
772 		rdata_maximum_wireformat_size(descriptor, rdata_count, rdatas);
773 	buffer_printf(output, " \\# %lu ", (unsigned long) size);
774 	for (i = 0; i < rdata_count; ++i) {
775 		if (rdata_atom_is_domain(descriptor->type, i)) {
776 			const dname_type *dname =
777 				domain_dname(rdata_atom_domain(rdatas[i]));
778 			hex_to_string(
779 				output, dname_name(dname), dname->name_size);
780 		} else {
781 			hex_to_string(output, rdata_atom_data(rdatas[i]),
782 				rdata_atom_size(rdatas[i]));
783 		}
784 	}
785 	return 1;
786 }
787 
788 int
789 print_rdata(buffer_type *output, rrtype_descriptor_type *descriptor,
790 	    rr_type *record)
791 {
792 	size_t i;
793 	size_t saved_position = buffer_position(output);
794 
795 	for (i = 0; i < record->rdata_count; ++i) {
796 		if (i == 0) {
797 			buffer_printf(output, "\t");
798 		} else if (descriptor->type == TYPE_SOA && i == 2) {
799 			buffer_printf(output, " (\n\t\t");
800 		} else {
801 			buffer_printf(output, " ");
802 		}
803 		if (!rdata_atom_to_string(
804 			    output,
805 			    (rdata_zoneformat_type) descriptor->zoneformat[i],
806 			    record->rdatas[i], record))
807 		{
808 			buffer_set_position(output, saved_position);
809 			return 0;
810 		}
811 	}
812 	if (descriptor->type == TYPE_SOA) {
813 		buffer_printf(output, " )");
814 	}
815 
816 	return 1;
817 }
818 
819 
820