xref: /freebsd/contrib/ldns/host2str.c (revision d0b2dbfa)
1 /*
2  * host2str.c
3  *
4  * conversion routines from the host format
5  * to the presentation format (strings)
6  *
7  * a Net::DNS like library for C
8  *
9  * (c) NLnet Labs, 2004-2006
10  *
11  * See the file LICENSE for the license
12  */
13 #include <ldns/config.h>
14 
15 #include <ldns/ldns.h>
16 #include <ldns/internal.h>
17 
18 #include <limits.h>
19 
20 #ifdef HAVE_SYS_SOCKET_H
21 #include <sys/socket.h>
22 #endif
23 #ifdef HAVE_ARPA_INET_H
24 #include <arpa/inet.h>
25 #endif
26 #ifdef HAVE_NETDB_H
27 #include <netdb.h>
28 #endif
29 #include <time.h>
30 #include <sys/time.h>
31 
32 #ifdef HAVE_SSL
33 #include <openssl/bn.h>
34 #include <openssl/rsa.h>
35 #ifdef USE_DSA
36 #include <openssl/dsa.h>
37 #endif
38 #endif
39 
40 #ifndef INET_ADDRSTRLEN
41 #define INET_ADDRSTRLEN 16
42 #endif
43 #ifndef INET6_ADDRSTRLEN
44 #define INET6_ADDRSTRLEN 46
45 #endif
46 
47 /* lookup tables for standard DNS stuff  */
48 
49 /* Taken from RFC 2535, section 7.  */
50 ldns_lookup_table ldns_algorithms[] = {
51         { LDNS_RSAMD5, "RSAMD5" },
52         { LDNS_DH, "DH" },
53         { LDNS_DSA, "DSA" },
54         { LDNS_ECC, "ECC" },
55         { LDNS_RSASHA1, "RSASHA1" },
56         { LDNS_DSA_NSEC3, "DSA-NSEC3-SHA1" },
57         { LDNS_RSASHA1_NSEC3, "RSASHA1-NSEC3-SHA1" },
58 	{ LDNS_RSASHA256, "RSASHA256"},
59 	{ LDNS_RSASHA512, "RSASHA512"},
60 	{ LDNS_ECC_GOST, "ECC-GOST"},
61         { LDNS_ECDSAP256SHA256, "ECDSAP256SHA256"},
62         { LDNS_ECDSAP384SHA384, "ECDSAP384SHA384"},
63 	{ LDNS_ED25519, "ED25519"},
64 	{ LDNS_ED448, "ED448"},
65         { LDNS_INDIRECT, "INDIRECT" },
66         { LDNS_PRIVATEDNS, "PRIVATEDNS" },
67         { LDNS_PRIVATEOID, "PRIVATEOID" },
68         { 0, NULL }
69 };
70 
71 /* Hashing algorithms used in the DS record */
72 ldns_lookup_table ldns_hashes[] = {
73         {LDNS_SHA1     , "SHA1" },      /* RFC 4034 */
74         {LDNS_SHA256   , "SHA256" },    /* RFC 4509 */
75         {LDNS_HASH_GOST, "HASH-GOST" }, /* RFC 5933 */
76         {LDNS_SHA384   , "SHA384" },    /* RFC 6605 */
77         { 0, NULL }
78 };
79 
80 /* Taken from RFC 4398  */
81 ldns_lookup_table ldns_cert_algorithms[] = {
82         { LDNS_CERT_PKIX, "PKIX" },
83         { LDNS_CERT_SPKI, "SPKI" },
84         { LDNS_CERT_PGP, "PGP" },
85         { LDNS_CERT_IPKIX, "IPKIX" },
86         { LDNS_CERT_ISPKI, "ISPKI" },
87         { LDNS_CERT_IPGP, "IPGP" },
88         { LDNS_CERT_ACPKIX, "ACPKIX" },
89         { LDNS_CERT_IACPKIX, "IACPKIX" },
90         { LDNS_CERT_URI, "URI" },
91         { LDNS_CERT_OID, "OID" },
92         { 0, NULL }
93 };
94 
95 /* classes  */
96 ldns_lookup_table ldns_rr_classes[] = {
97         { LDNS_RR_CLASS_IN, "IN" },
98         { LDNS_RR_CLASS_CH, "CH" },
99         { LDNS_RR_CLASS_HS, "HS" },
100         { LDNS_RR_CLASS_NONE, "NONE" },
101         { LDNS_RR_CLASS_ANY, "ANY" },
102         { 0, NULL }
103 };
104 
105 /* if these are used elsewhere */
106 ldns_lookup_table ldns_rcodes[] = {
107         { LDNS_RCODE_NOERROR, "NOERROR" },
108         { LDNS_RCODE_FORMERR, "FORMERR" },
109         { LDNS_RCODE_SERVFAIL, "SERVFAIL" },
110         { LDNS_RCODE_NXDOMAIN, "NXDOMAIN" },
111         { LDNS_RCODE_NOTIMPL, "NOTIMPL" },
112         { LDNS_RCODE_REFUSED, "REFUSED" },
113         { LDNS_RCODE_YXDOMAIN, "YXDOMAIN" },
114         { LDNS_RCODE_YXRRSET, "YXRRSET" },
115         { LDNS_RCODE_NXRRSET, "NXRRSET" },
116         { LDNS_RCODE_NOTAUTH, "NOTAUTH" },
117         { LDNS_RCODE_NOTZONE, "NOTZONE" },
118         { 0, NULL }
119 };
120 
121 ldns_lookup_table ldns_opcodes[] = {
122         { LDNS_PACKET_QUERY, "QUERY" },
123         { LDNS_PACKET_IQUERY, "IQUERY" },
124         { LDNS_PACKET_STATUS, "STATUS" },
125 	{ LDNS_PACKET_NOTIFY, "NOTIFY" },
126 	{ LDNS_PACKET_UPDATE, "UPDATE" },
127         { 0, NULL }
128 };
129 
130 const ldns_output_format   ldns_output_format_nocomments_record = { 0, NULL };
131 const ldns_output_format  *ldns_output_format_nocomments
132 			= &ldns_output_format_nocomments_record;
133 const ldns_output_format   ldns_output_format_onlykeyids_record = {
134 	LDNS_COMMENT_KEY, NULL
135 };
136 const ldns_output_format  *ldns_output_format_onlykeyids
137 			= &ldns_output_format_onlykeyids_record;
138 const ldns_output_format  *ldns_output_format_default
139 			= &ldns_output_format_onlykeyids_record;
140 
141 const ldns_output_format   ldns_output_format_bubblebabble_record = {
142 	LDNS_COMMENT_KEY | LDNS_COMMENT_BUBBLEBABBLE | LDNS_COMMENT_FLAGS, NULL
143 };
144 const ldns_output_format  *ldns_output_format_bubblebabble
145 			= &ldns_output_format_bubblebabble_record;
146 
147 static bool
148 ldns_output_format_covers_type(const ldns_output_format* fmt, ldns_rr_type t)
149 {
150 	return fmt && (fmt->flags & LDNS_FMT_RFC3597) &&
151 		((ldns_output_format_storage*)fmt)->bitmap &&
152 		ldns_nsec_bitmap_covers_type(
153 				((ldns_output_format_storage*)fmt)->bitmap, t);
154 }
155 
156 ldns_status
157 ldns_output_format_set_type(ldns_output_format* fmt, ldns_rr_type t)
158 {
159 	ldns_output_format_storage* fmt_st = (ldns_output_format_storage*)fmt;
160 	ldns_status s;
161 
162 	assert(fmt != NULL);
163 
164 	if (!(fmt_st->flags & LDNS_FMT_RFC3597)) {
165 		ldns_output_format_set(fmt, LDNS_FMT_RFC3597);
166 	}
167 	if (! fmt_st->bitmap) {
168 		s = ldns_rdf_bitmap_known_rr_types_space(&fmt_st->bitmap);
169 		if (s != LDNS_STATUS_OK) {
170 			return s;
171 		}
172 	}
173 	return ldns_nsec_bitmap_set_type(fmt_st->bitmap, t);
174 }
175 
176 ldns_status
177 ldns_output_format_clear_type(ldns_output_format* fmt, ldns_rr_type t)
178 {
179 	ldns_output_format_storage* fmt_st = (ldns_output_format_storage*)fmt;
180 	ldns_status s;
181 
182 	assert(fmt != NULL);
183 
184 	if (!(fmt_st->flags & LDNS_FMT_RFC3597)) {
185 		ldns_output_format_set(fmt, LDNS_FMT_RFC3597);
186 	}
187 	if (! fmt_st->bitmap) {
188 		s = ldns_rdf_bitmap_known_rr_types(&fmt_st->bitmap);
189 		if (s != LDNS_STATUS_OK) {
190 			return s;
191 		}
192 	}
193 	return ldns_nsec_bitmap_clear_type(fmt_st->bitmap, t);
194 }
195 
196 ldns_status
197 ldns_pkt_opcode2buffer_str(ldns_buffer *output, ldns_pkt_opcode opcode)
198 {
199 	ldns_lookup_table *lt = ldns_lookup_by_id(ldns_opcodes, opcode);
200 	if (lt && lt->name) {
201 		ldns_buffer_printf(output, "%s", lt->name);
202 	} else {
203 		ldns_buffer_printf(output, "OPCODE%u", opcode);
204 	}
205 	return ldns_buffer_status(output);
206 }
207 
208 ldns_status
209 ldns_pkt_rcode2buffer_str(ldns_buffer *output, ldns_pkt_rcode rcode)
210 {
211 	ldns_lookup_table *lt = ldns_lookup_by_id(ldns_rcodes, rcode);
212 	if (lt && lt->name) {
213 		ldns_buffer_printf(output, "%s", lt->name);
214 	} else {
215 		ldns_buffer_printf(output, "RCODE%u", rcode);
216 	}
217 	return ldns_buffer_status(output);
218 }
219 
220 ldns_status
221 ldns_algorithm2buffer_str(ldns_buffer *output,
222                           ldns_algorithm algorithm)
223 {
224 	ldns_lookup_table *lt = ldns_lookup_by_id(ldns_algorithms,
225 	                                          algorithm);
226 	if (lt && lt->name) {
227 		ldns_buffer_printf(output, "%s", lt->name);
228 	} else {
229 		ldns_buffer_printf(output, "ALG%u", algorithm);
230 	}
231 	return ldns_buffer_status(output);
232 }
233 
234 ldns_status
235 ldns_cert_algorithm2buffer_str(ldns_buffer *output,
236                                ldns_cert_algorithm cert_algorithm)
237 {
238 	ldns_lookup_table *lt = ldns_lookup_by_id(ldns_cert_algorithms,
239 	                                          cert_algorithm);
240 	if (lt && lt->name) {
241 		ldns_buffer_printf(output, "%s", lt->name);
242 	} else {
243 		ldns_buffer_printf(output, "CERT_ALG%u",
244 		                   cert_algorithm);
245 	}
246 	return ldns_buffer_status(output);
247 }
248 
249 char *
250 ldns_pkt_opcode2str(ldns_pkt_opcode opcode)
251 {
252 	char *str;
253 	ldns_buffer *buf;
254 
255 	buf = ldns_buffer_new(12);
256 	if (!buf) {
257 		return NULL;
258 	}
259 
260 	str = NULL;
261 	if (ldns_pkt_opcode2buffer_str(buf, opcode) == LDNS_STATUS_OK) {
262 		str = ldns_buffer_export2str(buf);
263 	}
264 
265 	ldns_buffer_free(buf);
266 	return str;
267 }
268 
269 char *
270 ldns_pkt_rcode2str(ldns_pkt_rcode rcode)
271 {
272 	char *str;
273 	ldns_buffer *buf;
274 
275 	buf = ldns_buffer_new(10);
276 	if (!buf) {
277 		return NULL;
278 	}
279 
280 	str = NULL;
281 	if (ldns_pkt_rcode2buffer_str(buf, rcode) == LDNS_STATUS_OK) {
282 		str = ldns_buffer_export2str(buf);
283 	}
284 
285 	ldns_buffer_free(buf);
286 	return str;
287 }
288 
289 char *
290 ldns_pkt_algorithm2str(ldns_algorithm algorithm)
291 {
292 	char *str;
293 	ldns_buffer *buf;
294 
295 	buf = ldns_buffer_new(10);
296 	if (!buf) {
297 		return NULL;
298 	}
299 
300 	str = NULL;
301 	if (ldns_algorithm2buffer_str(buf, algorithm)
302 	    == LDNS_STATUS_OK) {
303 		str = ldns_buffer_export2str(buf);
304 	}
305 
306 	ldns_buffer_free(buf);
307 	return str;
308 }
309 
310 char *
311 ldns_pkt_cert_algorithm2str(ldns_cert_algorithm cert_algorithm)
312 {
313 	char *str;
314 	ldns_buffer *buf;
315 
316 	buf = ldns_buffer_new(10);
317 	if (!buf) {
318 		return NULL;
319 	}
320 
321 	str = NULL;
322 	if (ldns_cert_algorithm2buffer_str(buf, cert_algorithm)
323 	    == LDNS_STATUS_OK) {
324 		str = ldns_buffer_export2str(buf);
325 	}
326 
327 	ldns_buffer_free(buf);
328 	return str;
329 }
330 
331 
332 /* do NOT pass compressed data here :p */
333 ldns_status
334 ldns_rdf2buffer_str_dname(ldns_buffer *output, const ldns_rdf *dname)
335 {
336 	/* can we do with 1 pos var? or without at all? */
337 	uint8_t src_pos = 0;
338 	uint8_t len;
339 	uint8_t *data;
340 	uint8_t i;
341 	unsigned char c;
342 
343 	data = (uint8_t*)ldns_rdf_data(dname);
344 	len = data[src_pos];
345 
346 	if (ldns_rdf_size(dname) > LDNS_MAX_DOMAINLEN) {
347 		/* too large, return */
348 		return LDNS_STATUS_DOMAINNAME_OVERFLOW;
349 	}
350 
351 	/* special case: root label */
352 	if (1 == ldns_rdf_size(dname)) {
353 		ldns_buffer_printf(output, ".");
354 	} else {
355 		while ((len > 0) && src_pos < ldns_rdf_size(dname)) {
356 			src_pos++;
357 			for(i = 0; i < len; i++) {
358 				/* paranoia check for various 'strange'
359 				   characters in dnames
360 				*/
361 				c = (unsigned char) data[src_pos];
362 				if(c == '.' || c == ';' ||
363 				   c == '(' || c == ')' ||
364 				   c == '\\') {
365 					ldns_buffer_printf(output, "\\%c",
366 							data[src_pos]);
367 				} else if (!(isascii(c) && isgraph(c))) {
368 					ldns_buffer_printf(output, "\\%03u",
369 						        data[src_pos]);
370 				} else {
371 					ldns_buffer_printf(output, "%c", data[src_pos]);
372 				}
373 				src_pos++;
374 			}
375 
376 			if (src_pos < ldns_rdf_size(dname)) {
377 				ldns_buffer_printf(output, ".");
378 			}
379 			len = data[src_pos];
380 		}
381 	}
382 	return ldns_buffer_status(output);
383 }
384 
385 ldns_status
386 ldns_rdf2buffer_str_int8(ldns_buffer *output, const ldns_rdf *rdf)
387 {
388 	uint8_t data = ldns_rdf_data(rdf)[0];
389 	ldns_buffer_printf(output, "%lu", (unsigned long) data);
390 	return ldns_buffer_status(output);
391 }
392 
393 ldns_status
394 ldns_rdf2buffer_str_int16(ldns_buffer *output, const ldns_rdf *rdf)
395 {
396 	uint16_t data = ldns_read_uint16(ldns_rdf_data(rdf));
397 	ldns_buffer_printf(output, "%lu", (unsigned long) data);
398 	return ldns_buffer_status(output);
399 }
400 
401 ldns_status
402 ldns_rdf2buffer_str_int32(ldns_buffer *output, const ldns_rdf *rdf)
403 {
404 	uint32_t data = ldns_read_uint32(ldns_rdf_data(rdf));
405 	ldns_buffer_printf(output, "%lu", (unsigned long) data);
406 	return ldns_buffer_status(output);
407 }
408 
409 ldns_status
410 ldns_rdf2buffer_str_time(ldns_buffer *output, const ldns_rdf *rdf)
411 {
412 	/* create a YYYYMMDDHHMMSS string if possible */
413 	struct tm tm;
414 	char date_buf[16];
415 
416 	memset(&tm, 0, sizeof(tm));
417 	if (ldns_serial_arithmetics_gmtime_r(ldns_rdf2native_int32(rdf), time(NULL), &tm)
418 	    && strftime(date_buf, 15, "%Y%m%d%H%M%S", &tm)) {
419 		ldns_buffer_printf(output, "%s", date_buf);
420 	}
421 	return ldns_buffer_status(output);
422 }
423 
424 ldns_status
425 ldns_rdf2buffer_str_a(ldns_buffer *output, const ldns_rdf *rdf)
426 {
427 	char str[INET_ADDRSTRLEN];
428 
429 	if (inet_ntop(AF_INET, ldns_rdf_data(rdf), str, INET_ADDRSTRLEN)) {
430 		ldns_buffer_printf(output, "%s", str);
431 	}
432 	return ldns_buffer_status(output);
433 }
434 
435 ldns_status
436 ldns_rdf2buffer_str_aaaa(ldns_buffer *output, const ldns_rdf *rdf)
437 {
438 	char str[INET6_ADDRSTRLEN];
439 
440 	if (inet_ntop(AF_INET6, ldns_rdf_data(rdf), str, INET6_ADDRSTRLEN)) {
441 		ldns_buffer_printf(output, "%s", str);
442 	}
443 
444 	return ldns_buffer_status(output);
445 }
446 
447 static void
448 ldns_characters2buffer_str(ldns_buffer* output,
449 		size_t amount, const uint8_t* characters)
450 {
451 	uint8_t ch;
452 	while (amount > 0) {
453 		ch = *characters++;
454 		if (isprint((int)ch) || ch == '\t') {
455 			if (ch == '\"' || ch == '\\')
456 				ldns_buffer_printf(output, "\\%c", ch);
457 			else
458 				ldns_buffer_printf(output, "%c", ch);
459 		} else {
460 			ldns_buffer_printf(output, "\\%03u",
461                                 (unsigned)(uint8_t) ch);
462 		}
463 		amount--;
464 	}
465 }
466 
467 ldns_status
468 ldns_rdf2buffer_str_str(ldns_buffer *output, const ldns_rdf *rdf)
469 {
470         if(ldns_rdf_size(rdf) < 1) {
471                 return LDNS_STATUS_WIRE_RDATA_ERR;
472         }
473         if((int)ldns_rdf_size(rdf) < (int)ldns_rdf_data(rdf)[0] + 1) {
474                 return LDNS_STATUS_WIRE_RDATA_ERR;
475         }
476 	ldns_buffer_printf(output, "\"");
477 	ldns_characters2buffer_str(output,
478 			ldns_rdf_data(rdf)[0], ldns_rdf_data(rdf) + 1);
479 	ldns_buffer_printf(output, "\"");
480 	return ldns_buffer_status(output);
481 }
482 
483 ldns_status
484 ldns_rdf2buffer_str_b64(ldns_buffer *output, const ldns_rdf *rdf)
485 {
486 	size_t size;
487 	char *b64;
488 
489 	if (ldns_rdf_size(rdf) == 0) {
490 		ldns_buffer_printf(output, "0");
491 		return ldns_buffer_status(output);
492 	} else
493 		size = ldns_b64_ntop_calculate_size(ldns_rdf_size(rdf));
494 
495 	if (!(b64 = LDNS_XMALLOC(char, size)))
496 		return LDNS_STATUS_MEM_ERR;
497 
498 	if (ldns_b64_ntop(ldns_rdf_data(rdf), ldns_rdf_size(rdf), b64, size)) {
499 		ldns_buffer_printf(output, "%s", b64);
500 	}
501 	LDNS_FREE(b64);
502 	return ldns_buffer_status(output);
503 }
504 
505 ldns_status
506 ldns_rdf2buffer_str_b32_ext(ldns_buffer *output, const ldns_rdf *rdf)
507 {
508 	size_t size;
509 	char *b32;
510 	if(ldns_rdf_size(rdf) == 0)
511 		return LDNS_STATUS_OK;
512         /* remove -1 for the b32-hash-len octet */
513 	size = ldns_b32_ntop_calculate_size(ldns_rdf_size(rdf) - 1);
514         /* add one for the end nul for the string */
515 	b32 = LDNS_XMALLOC(char, size + 1);
516 	if(!b32) return LDNS_STATUS_MEM_ERR;
517 	size = (size_t) ldns_b32_ntop_extended_hex(ldns_rdf_data(rdf) + 1,
518 		ldns_rdf_size(rdf) - 1, b32, size+1);
519 	if (size > 0) {
520 		ldns_buffer_printf(output, "%s", b32);
521 	}
522 	LDNS_FREE(b32);
523 	return ldns_buffer_status(output);
524 }
525 
526 ldns_status
527 ldns_rdf2buffer_str_hex(ldns_buffer *output, const ldns_rdf *rdf)
528 {
529 	size_t i;
530 	for (i = 0; i < ldns_rdf_size(rdf); i++) {
531 		ldns_buffer_printf(output, "%02x", ldns_rdf_data(rdf)[i]);
532 	}
533 
534 	return ldns_buffer_status(output);
535 }
536 
537 static ldns_status
538 ldns_rdf2buffer_str_type_fmt(ldns_buffer *output,
539 		const ldns_output_format* fmt, const ldns_rdf *rdf)
540 {
541         uint16_t data = ldns_read_uint16(ldns_rdf_data(rdf));
542 
543 	if (! ldns_output_format_covers_type(fmt, data) &&
544 			ldns_rr_descript(data) &&
545 			ldns_rr_descript(data)->_name) {
546 
547 		ldns_buffer_printf(output, "%s",ldns_rr_descript(data)->_name);
548 	} else {
549 		ldns_buffer_printf(output, "TYPE%u", data);
550 	}
551 	return  ldns_buffer_status(output);
552 }
553 
554 ldns_status
555 ldns_rdf2buffer_str_type(ldns_buffer *output, const ldns_rdf *rdf)
556 {
557 	return ldns_rdf2buffer_str_type_fmt(output,
558 			ldns_output_format_default, rdf);
559 }
560 
561 ldns_status
562 ldns_rdf2buffer_str_class(ldns_buffer *output, const ldns_rdf *rdf)
563 {
564 	uint16_t data = ldns_read_uint16(ldns_rdf_data(rdf));
565 	ldns_lookup_table *lt;
566 
567  	lt = ldns_lookup_by_id(ldns_rr_classes, (int) data);
568 	if (lt) {
569 		ldns_buffer_printf(output, "\t%s", lt->name);
570 	} else {
571 		ldns_buffer_printf(output, "\tCLASS%d", data);
572 	}
573 	return ldns_buffer_status(output);
574 }
575 
576 ldns_status
577 ldns_rdf2buffer_str_cert_alg(ldns_buffer *output, const ldns_rdf *rdf)
578 {
579         uint16_t data = ldns_read_uint16(ldns_rdf_data(rdf));
580 	ldns_lookup_table *lt;
581  	lt = ldns_lookup_by_id(ldns_cert_algorithms, (int) data);
582 	if (lt) {
583 		ldns_buffer_printf(output, "%s", lt->name);
584 	} else {
585 		ldns_buffer_printf(output, "%d", data);
586 	}
587 	return ldns_buffer_status(output);
588 }
589 
590 ldns_status
591 ldns_rdf2buffer_str_alg(ldns_buffer *output, const ldns_rdf *rdf)
592 {
593 	return ldns_rdf2buffer_str_int8(output, rdf);
594 }
595 
596 static void
597 loc_cm_print(ldns_buffer *output, uint8_t mantissa, uint8_t exponent)
598 {
599 	uint8_t i;
600 	/* is it 0.<two digits> ? */
601 	if(exponent < 2) {
602 		if(exponent == 1)
603 			mantissa *= 10;
604 		ldns_buffer_printf(output, "0.%02ld", (long)mantissa);
605 		return;
606 	}
607 	/* always <digit><string of zeros> */
608 	ldns_buffer_printf(output, "%d", (int)mantissa);
609 	for(i=0; i<exponent-2; i++)
610 		ldns_buffer_printf(output, "0");
611 }
612 
613 ldns_status
614 ldns_rr_type2buffer_str(ldns_buffer *output, const ldns_rr_type type)
615 {
616 	const ldns_rr_descriptor *descriptor;
617 
618 	descriptor = ldns_rr_descript(type);
619 
620 	switch (type) {
621 		case LDNS_RR_TYPE_IXFR:
622 			ldns_buffer_printf(output, "IXFR");
623 			break;
624 		case LDNS_RR_TYPE_AXFR:
625 			ldns_buffer_printf(output, "AXFR");
626 			break;
627 		case LDNS_RR_TYPE_MAILA:
628 			ldns_buffer_printf(output, "MAILA");
629 			break;
630 		case LDNS_RR_TYPE_MAILB:
631 			ldns_buffer_printf(output, "MAILB");
632 			break;
633 		case LDNS_RR_TYPE_ANY:
634 			ldns_buffer_printf(output, "ANY");
635 			break;
636 		default:
637 			if (descriptor && descriptor->_name) {
638 				ldns_buffer_printf(output, "%s", descriptor->_name);
639 			} else {
640 				ldns_buffer_printf(output, "TYPE%u", type);
641 			}
642 	}
643 	return ldns_buffer_status(output);
644 }
645 
646 char *
647 ldns_rr_type2str(const ldns_rr_type type)
648 {
649 	char *str;
650 	ldns_buffer *buf;
651 
652 	buf = ldns_buffer_new(10);
653 	if (!buf) {
654 		return NULL;
655 	}
656 
657 	str = NULL;
658 	if (ldns_rr_type2buffer_str(buf, type) == LDNS_STATUS_OK) {
659 		str = ldns_buffer_export2str(buf);
660 	}
661 
662 	ldns_buffer_free(buf);
663 	return str;
664 }
665 
666 
667 ldns_status
668 ldns_rr_class2buffer_str(ldns_buffer *output,
669                          const ldns_rr_class klass)
670 {
671 	ldns_lookup_table *lt;
672 
673 	lt = ldns_lookup_by_id(ldns_rr_classes, klass);
674 	if (lt) {
675 		ldns_buffer_printf(output, "%s", lt->name);
676 	} else {
677 		ldns_buffer_printf(output, "CLASS%d", klass);
678 	}
679 	return ldns_buffer_status(output);
680 }
681 
682 char *
683 ldns_rr_class2str(const ldns_rr_class klass)
684 {
685 	ldns_buffer *buf;
686 	char *str;
687 
688 	buf = ldns_buffer_new(10);
689 	if (!buf) {
690 		return NULL;
691 	}
692 
693 	str = NULL;
694 	if (ldns_rr_class2buffer_str(buf, klass) == LDNS_STATUS_OK) {
695 		str = ldns_buffer_export2str(buf);
696 	}
697 	ldns_buffer_free(buf);
698 	return str;
699 }
700 
701 ldns_status
702 ldns_rdf2buffer_str_loc(ldns_buffer *output, const ldns_rdf *rdf)
703 {
704 	/* we could do checking (ie degrees < 90 etc)? */
705 	uint8_t version;
706 	uint8_t size;
707 	uint8_t horizontal_precision;
708 	uint8_t vertical_precision;
709 	uint32_t longitude;
710 	uint32_t latitude;
711 	uint32_t altitude;
712 	char latitude_hemisphere;
713 	char longitude_hemisphere;
714 	uint32_t h;
715 	uint32_t m;
716 	double s;
717 
718 	uint32_t equator = (uint32_t) ldns_power(2, 31);
719 
720         if(ldns_rdf_size(rdf) < 1) {
721                 return LDNS_STATUS_WIRE_RDATA_ERR;
722         }
723        	version = ldns_rdf_data(rdf)[0];
724 	if (version == 0) {
725 		if(ldns_rdf_size(rdf) < 16) {
726 			return LDNS_STATUS_WIRE_RDATA_ERR;
727 		}
728 		size = ldns_rdf_data(rdf)[1];
729 		horizontal_precision = ldns_rdf_data(rdf)[2];
730 		vertical_precision = ldns_rdf_data(rdf)[3];
731 
732 		latitude = ldns_read_uint32(&ldns_rdf_data(rdf)[4]);
733 		longitude = ldns_read_uint32(&ldns_rdf_data(rdf)[8]);
734 		altitude = ldns_read_uint32(&ldns_rdf_data(rdf)[12]);
735 
736 		if (latitude > equator) {
737 			latitude_hemisphere = 'N';
738 			latitude = latitude - equator;
739 		} else {
740 			latitude_hemisphere = 'S';
741 			latitude = equator - latitude;
742 		}
743 		h = latitude / (1000 * 60 * 60);
744 		latitude = latitude % (1000 * 60 * 60);
745 		m = latitude / (1000 * 60);
746 		latitude = latitude % (1000 * 60);
747 		s = (double) latitude / 1000.0;
748 		ldns_buffer_printf(output, "%02u %02u %0.3f %c ",
749 			h, m, s, latitude_hemisphere);
750 
751 		if (longitude > equator) {
752 			longitude_hemisphere = 'E';
753 			longitude = longitude - equator;
754 		} else {
755 			longitude_hemisphere = 'W';
756 			longitude = equator - longitude;
757 		}
758 		h = longitude / (1000 * 60 * 60);
759 		longitude = longitude % (1000 * 60 * 60);
760 		m = longitude / (1000 * 60);
761 		longitude = longitude % (1000 * 60);
762 		s = (double) longitude / (1000.0);
763 		ldns_buffer_printf(output, "%02u %02u %0.3f %c ",
764 			h, m, s, longitude_hemisphere);
765 
766 		s = ((double) altitude) / 100;
767 		s -= 100000;
768 
769 		if(altitude%100 != 0)
770 			ldns_buffer_printf(output, "%.2f", s);
771 		else
772 			ldns_buffer_printf(output, "%.0f", s);
773 
774 		ldns_buffer_printf(output, "m ");
775 
776 		loc_cm_print(output, (size & 0xf0) >> 4, size & 0x0f);
777 		ldns_buffer_printf(output, "m ");
778 
779 		loc_cm_print(output, (horizontal_precision & 0xf0) >> 4,
780 			horizontal_precision & 0x0f);
781 		ldns_buffer_printf(output, "m ");
782 
783 		loc_cm_print(output, (vertical_precision & 0xf0) >> 4,
784 			vertical_precision & 0x0f);
785 		ldns_buffer_printf(output, "m");
786 
787 		return ldns_buffer_status(output);
788 	} else {
789 		return ldns_rdf2buffer_str_hex(output, rdf);
790 	}
791 }
792 
793 ldns_status
794 ldns_rdf2buffer_str_unknown(ldns_buffer *output, const ldns_rdf *rdf)
795 {
796 	ldns_buffer_printf(output, "\\# %u ", ldns_rdf_size(rdf));
797 	return ldns_rdf2buffer_str_hex(output, rdf);
798 }
799 
800 ldns_status
801 ldns_rdf2buffer_str_nsap(ldns_buffer *output, const ldns_rdf *rdf)
802 {
803 	ldns_buffer_printf(output, "0x");
804 	return ldns_rdf2buffer_str_hex(output, rdf);
805 }
806 
807 ldns_status
808 ldns_rdf2buffer_str_atma(ldns_buffer *output, const ldns_rdf *rdf)
809 {
810 	return ldns_rdf2buffer_str_hex(output, rdf);
811 }
812 
813 ldns_status
814 ldns_rdf2buffer_str_wks(ldns_buffer *output, const ldns_rdf *rdf)
815 {
816 	/* protocol, followed by bitmap of services */
817 	struct protoent *protocol;
818 	char *proto_name = NULL;
819 	uint8_t protocol_nr;
820 	struct servent *service;
821 	uint16_t current_service;
822 
823         if(ldns_rdf_size(rdf) < 1) {
824                 return LDNS_STATUS_WIRE_RDATA_ERR;
825         }
826 	protocol_nr = ldns_rdf_data(rdf)[0];
827 	protocol = getprotobynumber((int) protocol_nr);
828 	if (protocol && (protocol->p_name != NULL)) {
829 		proto_name = protocol->p_name;
830 		ldns_buffer_printf(output, "%s ", protocol->p_name);
831 	} else {
832 		ldns_buffer_printf(output, "%u ", protocol_nr);
833 	}
834 
835 #ifdef HAVE_ENDPROTOENT
836 	endprotoent();
837 #endif
838 
839 	for (current_service = 0;
840 	     current_service < (ldns_rdf_size(rdf)-1)*8; current_service++) {
841 		if (ldns_get_bit(&(ldns_rdf_data(rdf)[1]), current_service)) {
842 			service = getservbyport((int) htons(current_service),
843 			                        proto_name);
844 			if (service && service->s_name) {
845 				ldns_buffer_printf(output, "%s ", service->s_name);
846 			} else {
847 				ldns_buffer_printf(output, "%u ", current_service);
848 			}
849 #ifdef HAVE_ENDSERVENT
850 			endservent();
851 #endif
852 		}
853 		/* exit from loop before integer overflow */
854 		if(current_service == 65535) { break; }
855 	}
856 	return ldns_buffer_status(output);
857 }
858 
859 static ldns_status
860 ldns_rdf2buffer_str_nsec_fmt(ldns_buffer *output,
861 		const ldns_output_format* fmt, const ldns_rdf *rdf)
862 {
863 	/* Note: this code is duplicated in higher.c in
864 	 * ldns_nsec_type_check() function
865 	 */
866 	uint8_t window_block_nr;
867 	uint8_t bitmap_length;
868 	uint16_t type;
869 	uint16_t pos = 0;
870 	uint16_t bit_pos;
871 	uint8_t *data = ldns_rdf_data(rdf);
872 
873 	while((size_t)(pos + 2) < ldns_rdf_size(rdf)) {
874 		window_block_nr = data[pos];
875 		bitmap_length = data[pos + 1];
876 		pos += 2;
877 		if (ldns_rdf_size(rdf) < pos + bitmap_length) {
878 			return LDNS_STATUS_WIRE_RDATA_ERR;
879 		}
880 		for (bit_pos = 0; bit_pos < (bitmap_length) * 8; bit_pos++) {
881 			if (! ldns_get_bit(&data[pos], bit_pos)) {
882 				continue;
883 			}
884 			type = 256 * (uint16_t) window_block_nr + bit_pos;
885 
886 			if (! ldns_output_format_covers_type(fmt, type) &&
887 					ldns_rr_descript(type) &&
888 					ldns_rr_descript(type)->_name){
889 
890 				ldns_buffer_printf(output, "%s ",
891 						ldns_rr_descript(type)->_name);
892 			} else {
893 				ldns_buffer_printf(output, "TYPE%u ", type);
894 			}
895 		}
896 		pos += (uint16_t) bitmap_length;
897 	}
898 	return ldns_buffer_status(output);
899 }
900 
901 ldns_status
902 ldns_rdf2buffer_str_nsec(ldns_buffer *output, const ldns_rdf *rdf)
903 {
904 	return ldns_rdf2buffer_str_nsec_fmt(output,
905 			ldns_output_format_default, rdf);
906 }
907 
908 ldns_status
909 ldns_rdf2buffer_str_nsec3_salt(ldns_buffer *output, const ldns_rdf *rdf)
910 {
911 	uint8_t salt_length;
912 	uint8_t salt_pos;
913 
914 	uint8_t *data = ldns_rdf_data(rdf);
915 
916         if(ldns_rdf_size(rdf) < 1) {
917                 return LDNS_STATUS_WIRE_RDATA_ERR;
918         }
919 	salt_length = data[0];
920 	/* from now there are variable length entries so remember pos */
921 	if (salt_length == 0 || ((size_t)salt_length)+1 > ldns_rdf_size(rdf)) {
922 		ldns_buffer_printf(output, "- ");
923 	} else {
924 		for (salt_pos = 0; salt_pos < salt_length; salt_pos++) {
925 			ldns_buffer_printf(output, "%02x", data[1 + salt_pos]);
926 		}
927 		ldns_buffer_printf(output, " ");
928 	}
929 
930 	return ldns_buffer_status(output);
931 }
932 
933 ldns_status
934 ldns_rdf2buffer_str_period(ldns_buffer *output, const ldns_rdf *rdf)
935 {
936 	/* period is the number of seconds */
937 	if (ldns_rdf_size(rdf) != 4) {
938 		return LDNS_STATUS_WIRE_RDATA_ERR;
939 	}
940 	ldns_buffer_printf(output, "%u", ldns_read_uint32(ldns_rdf_data(rdf)));
941 	return ldns_buffer_status(output);
942 }
943 
944 ldns_status
945 ldns_rdf2buffer_str_tsigtime(ldns_buffer *output,const  ldns_rdf *rdf)
946 {
947 	/* tsigtime is 48 bits network order unsigned integer */
948 	uint64_t tsigtime = 0;
949 	uint8_t *data = ldns_rdf_data(rdf);
950 	uint64_t d0, d1, d2, d3, d4, d5;
951 
952 	if (ldns_rdf_size(rdf) < 6) {
953 		return LDNS_STATUS_WIRE_RDATA_ERR;
954 	}
955 	d0 = data[0]; /* cast to uint64 for shift operations */
956 	d1 = data[1];
957 	d2 = data[2];
958 	d3 = data[3];
959 	d4 = data[4];
960 	d5 = data[5];
961 	tsigtime = (d0<<40) | (d1<<32) | (d2<<24) | (d3<<16) | (d4<<8) | d5;
962 
963 	ldns_buffer_printf(output, "%llu ", (long long)tsigtime);
964 
965 	return ldns_buffer_status(output);
966 }
967 
968 ldns_status
969 ldns_rdf2buffer_str_apl(ldns_buffer *output, const ldns_rdf *rdf)
970 {
971 	uint8_t *data = ldns_rdf_data(rdf);
972 	uint16_t address_family;
973 	uint8_t prefix;
974 	bool negation;
975 	uint8_t adf_length;
976 	size_t i;
977 	size_t pos = 0;
978 
979 	while (pos < (unsigned int) ldns_rdf_size(rdf)) {
980                 if(pos + 3 >= (unsigned)ldns_rdf_size(rdf))
981                         return LDNS_STATUS_WIRE_RDATA_ERR;
982 		address_family = ldns_read_uint16(&data[pos]);
983 		prefix = data[pos + 2];
984 		negation = data[pos + 3] & LDNS_APL_NEGATION;
985 		adf_length = data[pos + 3] & LDNS_APL_MASK;
986 		if (address_family == LDNS_APL_IP4) {
987 			/* check if prefix < 32? */
988 			if (negation) {
989 				ldns_buffer_printf(output, "!");
990 			}
991 			ldns_buffer_printf(output, "%u:", address_family);
992 			/* address is variable length 0 - 4 */
993 			for (i = 0; i < 4; i++) {
994 				if (i > 0) {
995 					ldns_buffer_printf(output, ".");
996 				}
997 				if (i < (unsigned short) adf_length) {
998                                         if(pos+i+4 >= ldns_rdf_size(rdf))
999 					    return LDNS_STATUS_WIRE_RDATA_ERR;
1000 					ldns_buffer_printf(output, "%d",
1001 					                   data[pos + i + 4]);
1002 				} else {
1003 					ldns_buffer_printf(output, "0");
1004 				}
1005 			}
1006 			ldns_buffer_printf(output, "/%u ", prefix);
1007 		} else if (address_family == LDNS_APL_IP6) {
1008 			/* check if prefix < 128? */
1009 			if (negation) {
1010 				ldns_buffer_printf(output, "!");
1011 			}
1012 			ldns_buffer_printf(output, "%u:", address_family);
1013 			/* address is variable length 0 - 16 */
1014 			for (i = 0; i < 16; i++) {
1015 				if (i % 2 == 0 && i > 0) {
1016 					ldns_buffer_printf(output, ":");
1017 				}
1018 				if (i < (unsigned short) adf_length) {
1019                                         if(pos+i+4 >= ldns_rdf_size(rdf))
1020 					    return LDNS_STATUS_WIRE_RDATA_ERR;
1021 					ldns_buffer_printf(output, "%02x",
1022 					                   data[pos + i + 4]);
1023 				} else {
1024 					ldns_buffer_printf(output, "00");
1025 				}
1026 			}
1027 			ldns_buffer_printf(output, "/%u ", prefix);
1028 
1029 		} else {
1030 			/* unknown address family */
1031 			ldns_buffer_printf(output,
1032 					"Unknown address family: %u data: ",
1033 					address_family);
1034 			for (i = 1; i < (unsigned short) (4 + adf_length); i++) {
1035                                 if(pos+i >= ldns_rdf_size(rdf))
1036                                         return LDNS_STATUS_WIRE_RDATA_ERR;
1037 				ldns_buffer_printf(output, "%02x", data[i]);
1038 			}
1039 		}
1040 		pos += 4 + adf_length;
1041 	}
1042 	return ldns_buffer_status(output);
1043 }
1044 
1045 ldns_status
1046 ldns_rdf2buffer_str_int16_data(ldns_buffer *output, const ldns_rdf *rdf)
1047 {
1048 	size_t size;
1049 	char *b64;
1050 	if (ldns_rdf_size(rdf) < 2) {
1051 		return LDNS_STATUS_WIRE_RDATA_ERR;
1052 	}
1053 	/* Subtract the size (2) of the number that specifies the length */
1054 	size = ldns_b64_ntop_calculate_size(ldns_rdf_size(rdf) - 2);
1055 	ldns_buffer_printf(output, "%u ", ldns_rdf_size(rdf) - 2);
1056 	if (ldns_rdf_size(rdf) > 2) {
1057 		b64 = LDNS_XMALLOC(char, size);
1058 		if(!b64)
1059 			return LDNS_STATUS_MEM_ERR;
1060 
1061 		if (ldns_rdf_size(rdf) > 2 &&
1062 		ldns_b64_ntop(ldns_rdf_data(rdf) + 2,
1063 					ldns_rdf_size(rdf) - 2,
1064 					b64, size)) {
1065 			ldns_buffer_printf(output, "%s", b64);
1066 		}
1067 		LDNS_FREE(b64);
1068 	}
1069 	return ldns_buffer_status(output);
1070 }
1071 
1072 ldns_status
1073 ldns_rdf2buffer_str_ipseckey(ldns_buffer *output, const ldns_rdf *rdf)
1074 {
1075 	/* wire format from
1076 	   http://www.ietf.org/internet-drafts/draft-ietf-ipseckey-rr-12.txt
1077 	*/
1078 	uint8_t *data = ldns_rdf_data(rdf);
1079 	uint8_t precedence;
1080 	uint8_t gateway_type;
1081 	uint8_t algorithm;
1082 
1083 	ldns_rdf *gateway = NULL;
1084 	uint8_t *gateway_data;
1085 
1086 	size_t public_key_size;
1087 	uint8_t *public_key_data;
1088 	ldns_rdf *public_key;
1089 
1090 	size_t offset = 0;
1091 	ldns_status status;
1092 
1093 	if (ldns_rdf_size(rdf) < 3) {
1094 		return LDNS_STATUS_WIRE_RDATA_ERR;
1095 	}
1096 	precedence = data[0];
1097 	gateway_type = data[1];
1098 	algorithm = data[2];
1099 	offset = 3;
1100 
1101 	switch (gateway_type) {
1102 		case 0:
1103 			/* no gateway */
1104 			break;
1105 		case 1:
1106 			if (ldns_rdf_size(rdf) < offset + LDNS_IP4ADDRLEN) {
1107 				return LDNS_STATUS_ERR;
1108 			}
1109 			gateway_data = LDNS_XMALLOC(uint8_t, LDNS_IP4ADDRLEN);
1110                         if(!gateway_data)
1111                                 return LDNS_STATUS_MEM_ERR;
1112 			memcpy(gateway_data, &data[offset], LDNS_IP4ADDRLEN);
1113 			gateway = ldns_rdf_new(LDNS_RDF_TYPE_A,
1114 					LDNS_IP4ADDRLEN , gateway_data);
1115 			offset += LDNS_IP4ADDRLEN;
1116                         if(!gateway) {
1117                                 LDNS_FREE(gateway_data);
1118                                 return LDNS_STATUS_MEM_ERR;
1119                         }
1120 			break;
1121 		case 2:
1122 			if (ldns_rdf_size(rdf) < offset + LDNS_IP6ADDRLEN) {
1123 				return LDNS_STATUS_ERR;
1124 			}
1125 			gateway_data = LDNS_XMALLOC(uint8_t, LDNS_IP6ADDRLEN);
1126                         if(!gateway_data)
1127                                 return LDNS_STATUS_MEM_ERR;
1128 			memcpy(gateway_data, &data[offset], LDNS_IP6ADDRLEN);
1129 			offset += LDNS_IP6ADDRLEN;
1130 			gateway =
1131 				ldns_rdf_new(LDNS_RDF_TYPE_AAAA,
1132 						LDNS_IP6ADDRLEN, gateway_data);
1133                         if(!gateway) {
1134                                 LDNS_FREE(gateway_data);
1135                                 return LDNS_STATUS_MEM_ERR;
1136                         }
1137 			break;
1138 		case 3:
1139 			status = ldns_wire2dname(&gateway, data,
1140 					ldns_rdf_size(rdf), &offset);
1141                         if(status != LDNS_STATUS_OK)
1142                                 return status;
1143 			break;
1144 		default:
1145 			/* error? */
1146 			break;
1147 	}
1148 
1149 	if (ldns_rdf_size(rdf) <= offset) {
1150                 ldns_rdf_deep_free(gateway);
1151 		return LDNS_STATUS_ERR;
1152 	}
1153 	public_key_size = ldns_rdf_size(rdf) - offset;
1154 	public_key_data = LDNS_XMALLOC(uint8_t, public_key_size);
1155         if(!public_key_data) {
1156                 ldns_rdf_deep_free(gateway);
1157                 return LDNS_STATUS_MEM_ERR;
1158         }
1159 	memcpy(public_key_data, &data[offset], public_key_size);
1160 	public_key = ldns_rdf_new(LDNS_RDF_TYPE_B64,
1161 			public_key_size, public_key_data);
1162         if(!public_key) {
1163                 LDNS_FREE(public_key_data);
1164                 ldns_rdf_deep_free(gateway);
1165                 return LDNS_STATUS_MEM_ERR;
1166         }
1167 
1168 	ldns_buffer_printf(output, "%u %u %u ", precedence, gateway_type, algorithm);
1169 	if (gateway)
1170 	  	(void) ldns_rdf2buffer_str(output, gateway);
1171 	else
1172 		ldns_buffer_printf(output, ".");
1173 	ldns_buffer_printf(output, " ");
1174 	(void) ldns_rdf2buffer_str(output, public_key);
1175 
1176 	ldns_rdf_deep_free(gateway);
1177 	ldns_rdf_deep_free(public_key);
1178 
1179 	return ldns_buffer_status(output);
1180 }
1181 
1182 ldns_status
1183 ldns_rdf2buffer_str_ilnp64(ldns_buffer *output, const ldns_rdf *rdf)
1184 {
1185 	if (ldns_rdf_size(rdf) != 8) {
1186 		return LDNS_STATUS_WIRE_RDATA_ERR;
1187 	}
1188 	ldns_buffer_printf(output,"%.4x:%.4x:%.4x:%.4x",
1189 				ldns_read_uint16(ldns_rdf_data(rdf)),
1190 				ldns_read_uint16(ldns_rdf_data(rdf)+2),
1191 				ldns_read_uint16(ldns_rdf_data(rdf)+4),
1192 				ldns_read_uint16(ldns_rdf_data(rdf)+6));
1193 	return ldns_buffer_status(output);
1194 }
1195 
1196 ldns_status
1197 ldns_rdf2buffer_str_eui48(ldns_buffer *output, const ldns_rdf *rdf)
1198 {
1199 	if (ldns_rdf_size(rdf) != 6) {
1200 		return LDNS_STATUS_WIRE_RDATA_ERR;
1201 	}
1202 	ldns_buffer_printf(output,"%.2x-%.2x-%.2x-%.2x-%.2x-%.2x",
1203 				ldns_rdf_data(rdf)[0], ldns_rdf_data(rdf)[1],
1204 				ldns_rdf_data(rdf)[2], ldns_rdf_data(rdf)[3],
1205 				ldns_rdf_data(rdf)[4], ldns_rdf_data(rdf)[5]);
1206 	return ldns_buffer_status(output);
1207 }
1208 
1209 ldns_status
1210 ldns_rdf2buffer_str_eui64(ldns_buffer *output, const ldns_rdf *rdf)
1211 {
1212 	if (ldns_rdf_size(rdf) != 8) {
1213 		return LDNS_STATUS_WIRE_RDATA_ERR;
1214 	}
1215 	ldns_buffer_printf(output,"%.2x-%.2x-%.2x-%.2x-%.2x-%.2x-%.2x-%.2x",
1216 				ldns_rdf_data(rdf)[0], ldns_rdf_data(rdf)[1],
1217 				ldns_rdf_data(rdf)[2], ldns_rdf_data(rdf)[3],
1218 				ldns_rdf_data(rdf)[4], ldns_rdf_data(rdf)[5],
1219 				ldns_rdf_data(rdf)[6], ldns_rdf_data(rdf)[7]);
1220 	return ldns_buffer_status(output);
1221 }
1222 
1223 ldns_status
1224 ldns_rdf2buffer_str_tag(ldns_buffer *output, const ldns_rdf *rdf)
1225 {
1226 	size_t nchars;
1227 	const uint8_t* chars;
1228 	char ch;
1229 	if (ldns_rdf_size(rdf) < 2) {
1230 		return LDNS_STATUS_WIRE_RDATA_ERR;
1231 	}
1232 	nchars = ldns_rdf_data(rdf)[0];
1233 	if (nchars >= ldns_rdf_size(rdf) || /* should be rdf_size - 1 */
1234 			nchars < 1) {
1235 		return LDNS_STATUS_WIRE_RDATA_ERR;
1236 	}
1237 	chars = ldns_rdf_data(rdf) + 1;
1238 	while (nchars > 0) {
1239 		ch = (char)*chars++;
1240 		if (! isalnum((unsigned char)ch)) {
1241 			return LDNS_STATUS_WIRE_RDATA_ERR;
1242 		}
1243 		ldns_buffer_printf(output, "%c", ch);
1244 		nchars--;
1245 	}
1246 	return ldns_buffer_status(output);
1247 }
1248 
1249 ldns_status
1250 ldns_rdf2buffer_str_long_str(ldns_buffer *output, const ldns_rdf *rdf)
1251 {
1252 
1253 	ldns_buffer_printf(output, "\"");
1254 	ldns_characters2buffer_str(output,
1255 			ldns_rdf_size(rdf), ldns_rdf_data(rdf));
1256 	ldns_buffer_printf(output, "\"");
1257 	return ldns_buffer_status(output);
1258 }
1259 
1260 ldns_status
1261 ldns_rdf2buffer_str_hip(ldns_buffer *output, const ldns_rdf *rdf)
1262 {
1263 	uint8_t *data = ldns_rdf_data(rdf);
1264 	size_t rdf_size = ldns_rdf_size(rdf);
1265 	uint8_t hit_size;
1266 	uint16_t pk_size;
1267 	int written;
1268 
1269 	if (rdf_size < 6) {
1270 		return LDNS_STATUS_WIRE_RDATA_ERR;
1271 	}
1272 	if ((hit_size = data[0]) == 0 ||
1273 			(pk_size = ldns_read_uint16(data + 2)) == 0 ||
1274 			rdf_size < (size_t) hit_size + pk_size + 4) {
1275 
1276 		return LDNS_STATUS_WIRE_RDATA_ERR;
1277 	}
1278 
1279 	ldns_buffer_printf(output, "%d ", (int) data[1]);
1280 
1281 	for (data += 4; hit_size > 0; hit_size--, data++) {
1282 
1283 		ldns_buffer_printf(output, "%02x", (int) *data);
1284 	}
1285 	ldns_buffer_write_char(output, (uint8_t) ' ');
1286 
1287 	if (ldns_buffer_reserve(output,
1288 				ldns_b64_ntop_calculate_size(pk_size))) {
1289 
1290 		written = ldns_b64_ntop(data, pk_size,
1291 				(char *) ldns_buffer_current(output),
1292 				ldns_buffer_remaining(output));
1293 
1294 		if (written > 0 &&
1295 				written < (int) ldns_buffer_remaining(output)) {
1296 
1297 			output->_position += written;
1298 		}
1299 	}
1300 	return ldns_buffer_status(output);
1301 }
1302 
1303 /* implementation mimicked from ldns_rdf2buffer_str_ipseckey */
1304 ldns_status
1305 ldns_rdf2buffer_str_amtrelay(ldns_buffer *output, const ldns_rdf *rdf)
1306 {
1307 	/* wire format from
1308 	 * draft-ietf-mboned-driad-amt-discovery Section 4.2
1309 	 */
1310 	uint8_t *data = ldns_rdf_data(rdf);
1311 	uint8_t precedence;
1312 	uint8_t discovery_optional;
1313 	uint8_t relay_type;
1314 
1315 	ldns_rdf *relay = NULL;
1316 	uint8_t *relay_data;
1317 
1318 	size_t offset = 0;
1319 	ldns_status status;
1320 
1321 	if (ldns_rdf_size(rdf) < 2) {
1322 		return LDNS_STATUS_WIRE_RDATA_ERR;
1323 	}
1324 	precedence = data[0];
1325 	discovery_optional = ((data[1] & 0x80) >> 7);
1326 	relay_type = data[1] & 0x7F;
1327 	offset = 2;
1328 
1329 	switch (relay_type) {
1330 		case 0:
1331 			/* no relay */
1332 			break;
1333 		case 1:
1334 			if (ldns_rdf_size(rdf) < offset + LDNS_IP4ADDRLEN) {
1335 				return LDNS_STATUS_ERR;
1336 			}
1337 			relay_data = LDNS_XMALLOC(uint8_t, LDNS_IP4ADDRLEN);
1338                         if(!relay_data)
1339                                 return LDNS_STATUS_MEM_ERR;
1340 			memcpy(relay_data, &data[offset], LDNS_IP4ADDRLEN);
1341 			relay = ldns_rdf_new(LDNS_RDF_TYPE_A,
1342 					LDNS_IP4ADDRLEN , relay_data);
1343 			offset += LDNS_IP4ADDRLEN;
1344                         if(!relay) {
1345                                 LDNS_FREE(relay_data);
1346                                 return LDNS_STATUS_MEM_ERR;
1347                         }
1348 			break;
1349 		case 2:
1350 			if (ldns_rdf_size(rdf) < offset + LDNS_IP6ADDRLEN) {
1351 				return LDNS_STATUS_ERR;
1352 			}
1353 			relay_data = LDNS_XMALLOC(uint8_t, LDNS_IP6ADDRLEN);
1354                         if(!relay_data)
1355                                 return LDNS_STATUS_MEM_ERR;
1356 			memcpy(relay_data, &data[offset], LDNS_IP6ADDRLEN);
1357 			offset += LDNS_IP6ADDRLEN;
1358 			relay =
1359 				ldns_rdf_new(LDNS_RDF_TYPE_AAAA,
1360 						LDNS_IP6ADDRLEN, relay_data);
1361                         if(!relay) {
1362                                 LDNS_FREE(relay_data);
1363                                 return LDNS_STATUS_MEM_ERR;
1364                         }
1365 			break;
1366 		case 3:
1367 			status = ldns_wire2dname(&relay, data,
1368 					ldns_rdf_size(rdf), &offset);
1369                         if(status != LDNS_STATUS_OK)
1370                                 return status;
1371 			break;
1372 		default:
1373 			/* error? */
1374 			break;
1375 	}
1376 
1377 	if (ldns_rdf_size(rdf) != offset) {
1378                 ldns_rdf_deep_free(relay);
1379 		return LDNS_STATUS_ERR;
1380 	}
1381 	ldns_buffer_printf(output, "%u %u %u ",
1382 			precedence, discovery_optional, relay_type);
1383 	if (relay)
1384 	  	(void) ldns_rdf2buffer_str(output, relay);
1385 
1386 	ldns_rdf_deep_free(relay);
1387 	return ldns_buffer_status(output);
1388 }
1389 
1390 #ifdef RRTYPE_SVCB_HTTPS
1391 ldns_status svcparam_key2buffer_str(ldns_buffer *output, uint16_t key);
1392 
1393 static ldns_status
1394 svcparam_mandatory2buffer_str(ldns_buffer *output, size_t sz, uint8_t *data)
1395 {
1396 	if (sz % 2)
1397 		return LDNS_STATUS_INVALID_SVCPARAM_VALUE;
1398 
1399 	svcparam_key2buffer_str(output, ldns_read_uint16(data));
1400 	for (data += 2, sz -= 2; sz; data += 2, sz -= 2) {
1401 		ldns_buffer_write_char(output, ',');
1402 		svcparam_key2buffer_str(output, ldns_read_uint16(data));
1403 	}
1404 	return ldns_buffer_status(output);
1405 }
1406 
1407 static ldns_status
1408 svcparam_alpn2buffer_str(ldns_buffer *output, size_t sz, uint8_t *data)
1409 {
1410 	uint8_t *eod = data + sz, *dp;
1411 	bool quote = false;
1412 	size_t i;
1413 
1414 	for (dp = data; dp < eod && !quote; dp += 1 + *dp) {
1415 		if (dp + 1 + *dp > eod)
1416 			return LDNS_STATUS_INVALID_SVCPARAM_VALUE;
1417 
1418 		for (i = 0; i < *dp; i++)
1419 			if (isspace(dp[i + 1]))
1420 				break;
1421 		quote = i < *dp;
1422 	}
1423 	if (quote)
1424 		ldns_buffer_write_char(output, '"');
1425 	while (data < eod) {
1426 		uint8_t *eot = data + 1 + *data;
1427 
1428 		if (eot > eod)
1429 			return LDNS_STATUS_INVALID_SVCPARAM_VALUE;
1430 
1431 		if (eod - data < (int)sz)
1432 			ldns_buffer_write_char(output, ',');
1433 
1434 		for (data += 1; data < eot; data += 1) {
1435 			uint8_t ch = *data;
1436 
1437 			if (isprint(ch) || ch == '\t') {
1438 				if (ch == '"' ||  ch == ',' || ch == '\\')
1439 					ldns_buffer_write_char(output, '\\');
1440 				ldns_buffer_write_char(output, ch);
1441 			} else
1442 				ldns_buffer_printf(output, "\\%03u"
1443 				                         , (unsigned)ch);
1444 		}
1445 	}
1446 	if (quote)
1447 		ldns_buffer_write_char(output, '"');
1448 	return ldns_buffer_status(output);
1449 }
1450 
1451 static ldns_status
1452 svcparam_port2buffer_str(ldns_buffer *output, size_t sz, uint8_t *data)
1453 {
1454 	if (sz != 2)
1455 		return LDNS_STATUS_INVALID_SVCPARAM_VALUE;
1456 	ldns_buffer_printf(output, "%d", (int)ldns_read_uint16(data));
1457 	return ldns_buffer_status(output);
1458 }
1459 
1460 static ldns_status
1461 svcparam_ipv4hint2buffer_str(ldns_buffer *output, size_t sz, uint8_t *data)
1462 {
1463 	char str[INET_ADDRSTRLEN];
1464 
1465 	if (sz % 4 || !inet_ntop(AF_INET, data, str, INET_ADDRSTRLEN))
1466 		return LDNS_STATUS_INVALID_SVCPARAM_VALUE;
1467 
1468 	ldns_buffer_write_chars(output, str);
1469 
1470 	for (data += 4, sz -= 4; sz ; data += 4, sz -= 4 ) {
1471 		ldns_buffer_write_char(output, ',');
1472 		if (!inet_ntop(AF_INET, data, str, INET_ADDRSTRLEN))
1473 			return LDNS_STATUS_INVALID_SVCPARAM_VALUE;
1474 
1475 		ldns_buffer_write_chars(output, str);
1476 	}
1477 	return ldns_buffer_status(output);
1478 }
1479 
1480 static ldns_status
1481 svcparam_ech2buffer_str(ldns_buffer *output, size_t sz, uint8_t *data)
1482 {
1483 	size_t str_sz = ldns_b64_ntop_calculate_size(sz);
1484 	int written;
1485 
1486 	if (!ldns_buffer_reserve(output, str_sz))
1487 		return LDNS_STATUS_MEM_ERR;
1488 
1489 	written = ldns_b64_ntop( data, sz
1490 	                       , (char *)ldns_buffer_current(output), str_sz);
1491 	if (written > 0)
1492 		ldns_buffer_skip(output, written);
1493 	else
1494 		return LDNS_STATUS_INVALID_SVCPARAM_VALUE;
1495 
1496 	return ldns_buffer_status(output);
1497 }
1498 
1499 static ldns_status
1500 svcparam_ipv6hint2buffer_str(ldns_buffer *output, size_t sz, uint8_t *data)
1501 {
1502 	char str[INET6_ADDRSTRLEN];
1503 
1504 	if (sz % 16 || !inet_ntop(AF_INET6, data, str, INET6_ADDRSTRLEN))
1505 		return LDNS_STATUS_INVALID_SVCPARAM_VALUE;
1506 
1507 	ldns_buffer_write_chars(output, str);
1508 
1509 	for (data += 16, sz -= 16; sz ; data += 16, sz -= 16) {
1510 		ldns_buffer_write_char(output, ',');
1511 		if (!inet_ntop(AF_INET6, data, str, INET6_ADDRSTRLEN))
1512 			return LDNS_STATUS_INVALID_SVCPARAM_VALUE;
1513 
1514 		ldns_buffer_write_chars(output, str);
1515 	}
1516 	return ldns_buffer_status(output);
1517 }
1518 
1519 static ldns_status
1520 svcparam_value2buffer_str(ldns_buffer *output, size_t sz, uint8_t *data)
1521 {
1522 	uint8_t *eod = data + sz, *dp;
1523 	bool quote = false;
1524 
1525 	for (dp = data; dp < eod && !isspace(*dp); dp++)
1526 		; /* pass */
1527 
1528 	if ((quote = dp < eod))
1529 		ldns_buffer_write_char(output, '"');
1530 
1531 	for (dp = data; dp < eod; dp++) {
1532 		uint8_t ch = *dp;
1533 
1534 		if (isprint(ch) || ch == '\t') {
1535 			if (ch == '"' ||  ch == '\\')
1536 				ldns_buffer_write_char(output, '\\');
1537 			ldns_buffer_write_char(output, ch);
1538 		} else
1539 			ldns_buffer_printf(output, "\\%03u", (unsigned)ch);
1540 	}
1541 	if (quote)
1542 		ldns_buffer_write_char(output, '"');
1543 	return ldns_buffer_status(output);
1544 }
1545 
1546 ldns_status
1547 ldns_rdf2buffer_str_svcparams(ldns_buffer *output, const ldns_rdf *rdf)
1548 {
1549 	uint8_t    *data, *dp, *next_dp = NULL;
1550 	size_t      sz;
1551 	ldns_status st;
1552 
1553 	if (!output)
1554 		return LDNS_STATUS_NULL;
1555 
1556 	if (!rdf || !(data = ldns_rdf_data(rdf)) || !(sz = ldns_rdf_size(rdf)))
1557 		/* No svcparams is just fine. Just nothing to print. */
1558 		return LDNS_STATUS_OK;
1559 
1560 	for (dp = data; dp + 4 <= data + sz; dp = next_dp) {
1561 		ldns_svcparam_key key    = ldns_read_uint16(dp);
1562 		uint16_t          val_sz = ldns_read_uint16(dp + 2);
1563 
1564 		if ((next_dp = dp + 4 + val_sz) > data + sz)
1565 			return LDNS_STATUS_RDATA_OVERFLOW;
1566 
1567 		if (dp > data)
1568 			ldns_buffer_write_char(output, ' ');
1569 
1570 		if ((st = svcparam_key2buffer_str(output, key)))
1571 			return st;
1572 
1573 		if (val_sz == 0)
1574 			continue;
1575 		dp += 4;
1576 		ldns_buffer_write_char(output, '=');
1577 		switch (key) {
1578 		case LDNS_SVCPARAM_KEY_MANDATORY:
1579 			st = svcparam_mandatory2buffer_str(output, val_sz, dp);
1580 			break;
1581 		case LDNS_SVCPARAM_KEY_ALPN:
1582 			st = svcparam_alpn2buffer_str(output, val_sz, dp);
1583 			break;
1584 		case LDNS_SVCPARAM_KEY_NO_DEFAULT_ALPN:
1585 			return LDNS_STATUS_NO_SVCPARAM_VALUE_EXPECTED;
1586 		case LDNS_SVCPARAM_KEY_PORT:
1587 			st = svcparam_port2buffer_str(output, val_sz, dp);
1588 			break;
1589 		case LDNS_SVCPARAM_KEY_IPV4HINT:
1590 			st = svcparam_ipv4hint2buffer_str(output, val_sz, dp);
1591 			break;
1592 		case LDNS_SVCPARAM_KEY_ECH:
1593 			st = svcparam_ech2buffer_str(output, val_sz, dp);
1594 			break;
1595 		case LDNS_SVCPARAM_KEY_IPV6HINT:
1596 			st = svcparam_ipv6hint2buffer_str(output, val_sz, dp);
1597 			break;
1598 		default:
1599 			st = svcparam_value2buffer_str(output, val_sz, dp);
1600 			break;
1601 		}
1602 		if (st)
1603 			return st;
1604 	}
1605 	return ldns_buffer_status(output);
1606 }
1607 #else	/* #ifdef RRTYPE_SVCB_HTTPS */
1608 ldns_status
1609 ldns_rdf2buffer_str_svcparams(ldns_buffer *output, const ldns_rdf *rdf)
1610 {
1611 	(void)output; (void)rdf;
1612 	return LDNS_STATUS_NOT_IMPL;
1613 }
1614 #endif	/* #ifdef RRTYPE_SVCB_HTTPS */
1615 
1616 static ldns_status
1617 ldns_rdf2buffer_str_fmt(ldns_buffer *buffer,
1618 		const ldns_output_format* fmt, const ldns_rdf *rdf)
1619 {
1620 	ldns_status res = LDNS_STATUS_OK;
1621 
1622 	/*ldns_buffer_printf(buffer, "%u:", ldns_rdf_get_type(rdf));*/
1623 	if (rdf) {
1624 		switch(ldns_rdf_get_type(rdf)) {
1625 		case LDNS_RDF_TYPE_NONE:
1626 			break;
1627 		case LDNS_RDF_TYPE_DNAME:
1628 			res = ldns_rdf2buffer_str_dname(buffer, rdf);
1629 			break;
1630 		case LDNS_RDF_TYPE_INT8: /* Don't output mnemonics for these */
1631 		case LDNS_RDF_TYPE_ALG:
1632 		case LDNS_RDF_TYPE_CERTIFICATE_USAGE:
1633 		case LDNS_RDF_TYPE_SELECTOR:
1634 		case LDNS_RDF_TYPE_MATCHING_TYPE:
1635 			res = ldns_rdf2buffer_str_int8(buffer, rdf);
1636 			break;
1637 		case LDNS_RDF_TYPE_INT16:
1638 			res = ldns_rdf2buffer_str_int16(buffer, rdf);
1639 			break;
1640 		case LDNS_RDF_TYPE_INT32:
1641 			res = ldns_rdf2buffer_str_int32(buffer, rdf);
1642 			break;
1643 		case LDNS_RDF_TYPE_PERIOD:
1644 			res = ldns_rdf2buffer_str_period(buffer, rdf);
1645 			break;
1646 		case LDNS_RDF_TYPE_TSIGTIME:
1647 			res = ldns_rdf2buffer_str_tsigtime(buffer, rdf);
1648 			break;
1649 		case LDNS_RDF_TYPE_A:
1650 			res = ldns_rdf2buffer_str_a(buffer, rdf);
1651 			break;
1652 		case LDNS_RDF_TYPE_AAAA:
1653 			res = ldns_rdf2buffer_str_aaaa(buffer, rdf);
1654 			break;
1655 		case LDNS_RDF_TYPE_STR:
1656 			res = ldns_rdf2buffer_str_str(buffer, rdf);
1657 			break;
1658 		case LDNS_RDF_TYPE_APL:
1659 			res = ldns_rdf2buffer_str_apl(buffer, rdf);
1660 			break;
1661 		case LDNS_RDF_TYPE_B32_EXT:
1662 			res = ldns_rdf2buffer_str_b32_ext(buffer, rdf);
1663 			break;
1664 		case LDNS_RDF_TYPE_B64:
1665 			res = ldns_rdf2buffer_str_b64(buffer, rdf);
1666 			break;
1667 		case LDNS_RDF_TYPE_HEX:
1668 			res = ldns_rdf2buffer_str_hex(buffer, rdf);
1669 			break;
1670 		case LDNS_RDF_TYPE_NSEC:
1671 			res = ldns_rdf2buffer_str_nsec_fmt(buffer, fmt, rdf);
1672 			break;
1673 		case LDNS_RDF_TYPE_NSEC3_SALT:
1674 			res = ldns_rdf2buffer_str_nsec3_salt(buffer, rdf);
1675 			break;
1676 		case LDNS_RDF_TYPE_TYPE:
1677 			res = ldns_rdf2buffer_str_type_fmt(buffer, fmt, rdf);
1678 			break;
1679 		case LDNS_RDF_TYPE_CLASS:
1680 			res = ldns_rdf2buffer_str_class(buffer, rdf);
1681 			break;
1682 		case LDNS_RDF_TYPE_CERT_ALG:
1683 			res = ldns_rdf2buffer_str_cert_alg(buffer, rdf);
1684 			break;
1685 		case LDNS_RDF_TYPE_UNKNOWN:
1686 			res = ldns_rdf2buffer_str_unknown(buffer, rdf);
1687 			break;
1688 		case LDNS_RDF_TYPE_TIME:
1689 			res = ldns_rdf2buffer_str_time(buffer, rdf);
1690 			break;
1691 		case LDNS_RDF_TYPE_HIP:
1692 			res = ldns_rdf2buffer_str_hip(buffer, rdf);
1693 			break;
1694 		case LDNS_RDF_TYPE_LOC:
1695 			res = ldns_rdf2buffer_str_loc(buffer, rdf);
1696 			break;
1697 		case LDNS_RDF_TYPE_WKS:
1698 		case LDNS_RDF_TYPE_SERVICE:
1699 			res = ldns_rdf2buffer_str_wks(buffer, rdf);
1700 			break;
1701 		case LDNS_RDF_TYPE_NSAP:
1702 			res = ldns_rdf2buffer_str_nsap(buffer, rdf);
1703 			break;
1704 		case LDNS_RDF_TYPE_ATMA:
1705 			res = ldns_rdf2buffer_str_atma(buffer, rdf);
1706 			break;
1707 		case LDNS_RDF_TYPE_IPSECKEY:
1708 			res = ldns_rdf2buffer_str_ipseckey(buffer, rdf);
1709 			break;
1710 		case LDNS_RDF_TYPE_INT16_DATA:
1711 			res = ldns_rdf2buffer_str_int16_data(buffer, rdf);
1712 			break;
1713 		case LDNS_RDF_TYPE_NSEC3_NEXT_OWNER:
1714 			res = ldns_rdf2buffer_str_b32_ext(buffer, rdf);
1715 			break;
1716 		case LDNS_RDF_TYPE_ILNP64:
1717 			res = ldns_rdf2buffer_str_ilnp64(buffer, rdf);
1718 			break;
1719 		case LDNS_RDF_TYPE_EUI48:
1720 			res = ldns_rdf2buffer_str_eui48(buffer, rdf);
1721 			break;
1722 		case LDNS_RDF_TYPE_EUI64:
1723 			res = ldns_rdf2buffer_str_eui64(buffer, rdf);
1724 			break;
1725 		case LDNS_RDF_TYPE_TAG:
1726 			res = ldns_rdf2buffer_str_tag(buffer, rdf);
1727 			break;
1728 		case LDNS_RDF_TYPE_LONG_STR:
1729 			res = ldns_rdf2buffer_str_long_str(buffer, rdf);
1730 			break;
1731 		case LDNS_RDF_TYPE_AMTRELAY:
1732 			res = ldns_rdf2buffer_str_amtrelay(buffer, rdf);
1733 			break;
1734 		case LDNS_RDF_TYPE_SVCPARAMS:
1735 			res = ldns_rdf2buffer_str_svcparams(buffer, rdf);
1736 			break;
1737 		}
1738 	} else {
1739 		/** This will write mangled RRs */
1740 		ldns_buffer_printf(buffer, "(null) ");
1741 		res = LDNS_STATUS_ERR;
1742 	}
1743 	return res;
1744 }
1745 
1746 ldns_status
1747 ldns_rdf2buffer_str(ldns_buffer *buffer, const ldns_rdf *rdf)
1748 {
1749 	return ldns_rdf2buffer_str_fmt(buffer,ldns_output_format_default,rdf);
1750 }
1751 
1752 static ldns_rdf *
1753 ldns_b32_ext2dname(const ldns_rdf *rdf)
1754 {
1755 	size_t size;
1756 	char *b32;
1757 	ldns_rdf *out;
1758 	if(ldns_rdf_size(rdf) == 0)
1759 		return NULL;
1760         /* remove -1 for the b32-hash-len octet */
1761 	size = ldns_b32_ntop_calculate_size(ldns_rdf_size(rdf) - 1);
1762         /* add one for the end nul for the string */
1763 	b32 = LDNS_XMALLOC(char, size + 2);
1764 	if (b32) {
1765 		if (ldns_b32_ntop_extended_hex(ldns_rdf_data(rdf) + 1,
1766 				ldns_rdf_size(rdf) - 1, b32, size+1) > 0) {
1767 			b32[size] = '.';
1768 			b32[size+1] = '\0';
1769 			if (ldns_str2rdf_dname(&out, b32) == LDNS_STATUS_OK) {
1770 				LDNS_FREE(b32);
1771 				return out;
1772 			}
1773 		}
1774 		LDNS_FREE(b32);
1775 	}
1776 	return NULL;
1777 }
1778 
1779 static ldns_status
1780 ldns_rr2buffer_str_rfc3597(ldns_buffer *output, const ldns_rr *rr)
1781 {
1782 	size_t total_rdfsize = 0;
1783 	size_t i, j;
1784 
1785 	ldns_buffer_printf(output, "TYPE%u\t", ldns_rr_get_type(rr));
1786 	for (i = 0; i < ldns_rr_rd_count(rr); i++) {
1787 		total_rdfsize += ldns_rdf_size(ldns_rr_rdf(rr, i));
1788 	}
1789 	if (total_rdfsize == 0) {
1790 		ldns_buffer_printf(output, "\\# 0\n");
1791 		return ldns_buffer_status(output);
1792 	}
1793 	ldns_buffer_printf(output, "\\# %d ", total_rdfsize);
1794 	for (i = 0; i < ldns_rr_rd_count(rr); i++) {
1795 		for (j = 0; j < ldns_rdf_size(ldns_rr_rdf(rr, i)); j++) {
1796 			ldns_buffer_printf(output, "%.2x",
1797 					ldns_rdf_data(ldns_rr_rdf(rr, i))[j]);
1798 		}
1799 	}
1800 	ldns_buffer_printf(output, "\n");
1801 	return ldns_buffer_status(output);
1802 }
1803 
1804 ldns_status
1805 ldns_rr2buffer_str_fmt(ldns_buffer *output,
1806 		const ldns_output_format *fmt, const ldns_rr *rr)
1807 {
1808 	uint16_t i, flags;
1809 	ldns_status status = LDNS_STATUS_OK;
1810 	ldns_output_format_storage* fmt_st = (ldns_output_format_storage*)fmt;
1811 
1812 	if (fmt_st == NULL) {
1813 		fmt_st = (ldns_output_format_storage*)
1814 			  ldns_output_format_default;
1815 	}
1816 	if (!(fmt_st->flags & LDNS_FMT_SHORT)) {
1817 		if (!rr) {
1818 			if (LDNS_COMMENT_NULLS & fmt_st->flags) {
1819 				ldns_buffer_printf(output, "; (null)\n");
1820 			}
1821 			return ldns_buffer_status(output);
1822 		}
1823 		if (ldns_rr_owner(rr)) {
1824 			status = ldns_rdf2buffer_str_dname(output, ldns_rr_owner(rr));
1825 		}
1826 		if (status != LDNS_STATUS_OK) {
1827 			return status;
1828 		}
1829 
1830 		/* TTL should NOT be printed if it is a question */
1831 		if (!ldns_rr_is_question(rr)) {
1832 			ldns_buffer_printf(output, "\t%u", (unsigned)ldns_rr_ttl(rr));
1833 		}
1834 
1835 		ldns_buffer_printf(output, "\t");
1836 		status = ldns_rr_class2buffer_str(output, ldns_rr_get_class(rr));
1837 		if (status != LDNS_STATUS_OK) {
1838 			return status;
1839 		}
1840 		ldns_buffer_printf(output, "\t");
1841 
1842 		if (ldns_output_format_covers_type(fmt, ldns_rr_get_type(rr))) {
1843 			return ldns_rr2buffer_str_rfc3597(output, rr);
1844 		}
1845 		status = ldns_rr_type2buffer_str(output, ldns_rr_get_type(rr));
1846 		if (status != LDNS_STATUS_OK) {
1847 			return status;
1848 		}
1849 
1850 		if (ldns_rr_rd_count(rr) > 0) {
1851 			ldns_buffer_printf(output, "\t");
1852 		} else if (!ldns_rr_is_question(rr)) {
1853 			ldns_buffer_printf(output, "\t\\# 0");
1854 		}
1855 	} else if (ldns_rr_rd_count(rr) == 0) {
1856 		/* assert(fmt_st->flags & LDNS_FMT_SHORT); */
1857 
1858 		ldns_buffer_printf(output, "# 0");
1859 	}
1860 	for (i = 0; i < ldns_rr_rd_count(rr); i++) {
1861 		/* ldns_rdf2buffer_str handles NULL input fine! */
1862 		if ((fmt_st->flags & LDNS_FMT_ZEROIZE_RRSIGS) &&
1863 				(ldns_rr_get_type(rr) == LDNS_RR_TYPE_RRSIG) &&
1864 				((/* inception  */ i == 4 &&
1865 				  ldns_rdf_get_type(ldns_rr_rdf(rr, 4)) ==
1866 							LDNS_RDF_TYPE_TIME) ||
1867 				  (/* expiration */ i == 5 &&
1868 				   ldns_rdf_get_type(ldns_rr_rdf(rr, 5)) ==
1869 				   			LDNS_RDF_TYPE_TIME) ||
1870 				  (/* signature  */ i == 8 &&
1871 				   ldns_rdf_get_type(ldns_rr_rdf(rr, 8)) ==
1872 				   			LDNS_RDF_TYPE_B64))) {
1873 
1874 			ldns_buffer_printf(output, "(null)");
1875 			status = ldns_buffer_status(output);
1876 		} else if ((fmt_st->flags & LDNS_FMT_PAD_SOA_SERIAL) &&
1877 				(ldns_rr_get_type(rr) == LDNS_RR_TYPE_SOA) &&
1878 				/* serial */ i == 2 &&
1879 			 	ldns_rdf_get_type(ldns_rr_rdf(rr, 2)) ==
1880 			 				LDNS_RDF_TYPE_INT32) {
1881 			ldns_buffer_printf(output, "%10lu",
1882 				(unsigned long) ldns_read_uint32(
1883 					ldns_rdf_data(ldns_rr_rdf(rr, 2))));
1884 			status = ldns_buffer_status(output);
1885 		} else {
1886 			status = ldns_rdf2buffer_str_fmt(output,
1887 					fmt, ldns_rr_rdf(rr, i));
1888 		}
1889 		if(status != LDNS_STATUS_OK)
1890 			return status;
1891 		if (i < ldns_rr_rd_count(rr) - 1) {
1892 			ldns_buffer_printf(output, " ");
1893 		}
1894 	}
1895 	/* per RR special comments - handy for DNSSEC types */
1896 	/* check to prevent question sec. rr from
1897 	 * getting here */
1898 	if (ldns_rr_rd_count(rr) > 0) {
1899 		switch (ldns_rr_get_type(rr)) {
1900 		case LDNS_RR_TYPE_DNSKEY:
1901 			/* if ldns_rr_rd_count(rr) > 0
1902 				then ldns_rr_rdf(rr, 0) exists! */
1903 			if (! (fmt_st->flags & LDNS_COMMENT_KEY)) {
1904 				break;
1905 			}
1906 			flags = ldns_rdf2native_int16(ldns_rr_rdf(rr, 0));
1907 			ldns_buffer_printf(output, " ;{");
1908 			if (fmt_st->flags & LDNS_COMMENT_KEY_ID) {
1909 				ldns_buffer_printf(output, "id = %u",
1910 					(unsigned int) ldns_calc_keytag(rr));
1911 			}
1912 			if ((fmt_st->flags & LDNS_COMMENT_KEY_TYPE) &&
1913 					(flags & LDNS_KEY_ZONE_KEY)){
1914 
1915 				if (flags & LDNS_KEY_SEP_KEY) {
1916 					ldns_buffer_printf(output, " (ksk)");
1917 				} else {
1918 					ldns_buffer_printf(output, " (zsk)");
1919 				}
1920 				if (fmt_st->flags & LDNS_COMMENT_KEY_SIZE){
1921 					ldns_buffer_printf(output, ", ");
1922 				}
1923 			} else if (fmt_st->flags
1924 					& (LDNS_COMMENT_KEY_ID
1925 						|LDNS_COMMENT_KEY_SIZE)) {
1926 				ldns_buffer_printf( output, ", ");
1927 			}
1928 			if (fmt_st->flags & LDNS_COMMENT_KEY_SIZE) {
1929 				ldns_buffer_printf(output, "size = %db",
1930 					ldns_rr_dnskey_key_size(rr));
1931 			}
1932 			ldns_buffer_printf(output, "}");
1933 			break;
1934 		case LDNS_RR_TYPE_RRSIG:
1935 			if ((fmt_st->flags & LDNS_COMMENT_KEY)
1936 					&& (fmt_st->flags& LDNS_COMMENT_RRSIGS)
1937 					&& ldns_rr_rdf(rr, 6) != NULL) {
1938 				ldns_buffer_printf(output, " ;{id = %d}",
1939 						ldns_rdf2native_int16(
1940 							ldns_rr_rdf(rr, 6)));
1941 			}
1942 			break;
1943 		case LDNS_RR_TYPE_DS:
1944 			if ((fmt_st->flags & LDNS_COMMENT_BUBBLEBABBLE) &&
1945 					ldns_rr_rdf(rr, 3) != NULL) {
1946 
1947 				uint8_t *data = ldns_rdf_data(
1948 						ldns_rr_rdf(rr, 3));
1949 				size_t len = ldns_rdf_size(ldns_rr_rdf(rr, 3));
1950 				char *babble = ldns_bubblebabble(data, len);
1951 				if(babble) {
1952 					ldns_buffer_printf(output,
1953 							" ;{%s}", babble);
1954 				}
1955 				LDNS_FREE(babble);
1956 			}
1957 			break;
1958 		case LDNS_RR_TYPE_NSEC3:
1959 			if (! (fmt_st->flags & LDNS_COMMENT_FLAGS) &&
1960 				! (fmt_st->flags & LDNS_COMMENT_NSEC3_CHAIN)) {
1961 				break;
1962 			}
1963 			ldns_buffer_printf(output, " ;{");
1964 			if ((fmt_st->flags & LDNS_COMMENT_FLAGS)) {
1965 				if (ldns_nsec3_optout(rr)) {
1966 					ldns_buffer_printf(output,
1967 						" flags: optout");
1968 				} else {
1969 					ldns_buffer_printf(output," flags: -");
1970 				}
1971 				if (fmt_st->flags & LDNS_COMMENT_NSEC3_CHAIN &&
1972 						fmt_st->hashmap != NULL) {
1973 					ldns_buffer_printf(output, ", ");
1974 				}
1975 			}
1976 			if (fmt_st->flags & LDNS_COMMENT_NSEC3_CHAIN &&
1977 					fmt_st->hashmap != NULL) {
1978 				ldns_rbnode_t *node;
1979 				ldns_rdf *key = ldns_dname_label(
1980 						ldns_rr_owner(rr), 0);
1981 				if (key) {
1982 					node = ldns_rbtree_search(
1983 						fmt_st->hashmap,
1984 						(void *) key);
1985 					if (node->data) {
1986 						ldns_buffer_printf(output,
1987 							"from: ");
1988 						(void) ldns_rdf2buffer_str(
1989 							output,
1990 							ldns_dnssec_name_name(
1991 							   (ldns_dnssec_name*)
1992 							   node->data
1993 							));
1994 					}
1995 					ldns_rdf_deep_free(key);
1996 				}
1997 				key = ldns_b32_ext2dname(
1998 						ldns_nsec3_next_owner(rr));
1999 				if (key) {
2000 					node = ldns_rbtree_search(
2001 						fmt_st->hashmap,
2002 						(void *) key);
2003 					if (node->data) {
2004 						ldns_buffer_printf(output,
2005 							" to: ");
2006 						(void) ldns_rdf2buffer_str(
2007 							output,
2008 							ldns_dnssec_name_name(
2009 							   (ldns_dnssec_name*)
2010 							   node->data
2011 							));
2012 					}
2013 					ldns_rdf_deep_free(key);
2014 				}
2015 			}
2016 			ldns_buffer_printf(output, "}");
2017 			break;
2018 		default:
2019 			break;
2020 
2021 		}
2022 	}
2023 	/* last */
2024 	ldns_buffer_printf(output, "\n");
2025 	return ldns_buffer_status(output);
2026 }
2027 
2028 ldns_status
2029 ldns_rr2buffer_str(ldns_buffer *output, const ldns_rr *rr)
2030 {
2031 	return ldns_rr2buffer_str_fmt(output, ldns_output_format_default, rr);
2032 }
2033 
2034 ldns_status
2035 ldns_rr_list2buffer_str_fmt(ldns_buffer *output,
2036 		const ldns_output_format *fmt, const ldns_rr_list *list)
2037 {
2038 	uint16_t i;
2039 
2040 	for(i = 0; i < ldns_rr_list_rr_count(list); i++) {
2041 		(void) ldns_rr2buffer_str_fmt(output, fmt,
2042 				ldns_rr_list_rr(list, i));
2043 	}
2044 	return ldns_buffer_status(output);
2045 }
2046 
2047 ldns_status
2048 ldns_rr_list2buffer_str(ldns_buffer *output, const ldns_rr_list *list)
2049 {
2050 	return ldns_rr_list2buffer_str_fmt(
2051 			output, ldns_output_format_default, list);
2052 }
2053 
2054 ldns_status
2055 ldns_pktheader2buffer_str(ldns_buffer *output, const ldns_pkt *pkt)
2056 {
2057 	ldns_lookup_table *opcode = ldns_lookup_by_id(ldns_opcodes,
2058 			                    (int) ldns_pkt_get_opcode(pkt));
2059 	ldns_lookup_table *rcode = ldns_lookup_by_id(ldns_rcodes,
2060 			                    (int) ldns_pkt_get_rcode(pkt));
2061 
2062 	ldns_buffer_printf(output, ";; ->>HEADER<<- ");
2063 	if (opcode) {
2064 		ldns_buffer_printf(output, "opcode: %s, ", opcode->name);
2065 	} else {
2066 		ldns_buffer_printf(output, "opcode: ?? (%u), ",
2067 				ldns_pkt_get_opcode(pkt));
2068 	}
2069 	if (rcode) {
2070 		ldns_buffer_printf(output, "rcode: %s, ", rcode->name);
2071 	} else {
2072 		ldns_buffer_printf(output, "rcode: ?? (%u), ", ldns_pkt_get_rcode(pkt));
2073 	}
2074 	ldns_buffer_printf(output, "id: %d\n", ldns_pkt_id(pkt));
2075 	ldns_buffer_printf(output, ";; flags: ");
2076 
2077 	if (ldns_pkt_qr(pkt)) {
2078 		ldns_buffer_printf(output, "qr ");
2079 	}
2080 	if (ldns_pkt_aa(pkt)) {
2081 		ldns_buffer_printf(output, "aa ");
2082 	}
2083 	if (ldns_pkt_tc(pkt)) {
2084 		ldns_buffer_printf(output, "tc ");
2085 	}
2086 	if (ldns_pkt_rd(pkt)) {
2087 		ldns_buffer_printf(output, "rd ");
2088 	}
2089 	if (ldns_pkt_cd(pkt)) {
2090 		ldns_buffer_printf(output, "cd ");
2091 	}
2092 	if (ldns_pkt_ra(pkt)) {
2093 		ldns_buffer_printf(output, "ra ");
2094 	}
2095 	if (ldns_pkt_ad(pkt)) {
2096 		ldns_buffer_printf(output, "ad ");
2097 	}
2098 	ldns_buffer_printf(output, "; ");
2099 	ldns_buffer_printf(output, "QUERY: %u, ", ldns_pkt_qdcount(pkt));
2100 	ldns_buffer_printf(output, "ANSWER: %u, ", ldns_pkt_ancount(pkt));
2101 	ldns_buffer_printf(output, "AUTHORITY: %u, ", ldns_pkt_nscount(pkt));
2102 	ldns_buffer_printf(output, "ADDITIONAL: %u ", ldns_pkt_arcount(pkt));
2103 	return ldns_buffer_status(output);
2104 }
2105 
2106 
2107 /* print EDNS option data in the Dig format: 76 61 6c 69 ... */
2108 static void
2109 ldns_edns_hex_data2buffer_str(ldns_buffer* output, uint8_t* data, size_t len)
2110 {
2111 	size_t j;
2112 	for (j = 0; j < len; j++) {
2113 		ldns_buffer_printf(output, " %02x", data[j]);
2114 	}
2115 }
2116 
2117 static ldns_status
2118 ldns_edns_llq2buffer_str(ldns_buffer* output, uint8_t* data, size_t len)
2119 {
2120 	/* LLQ constants */
2121 	const char* llq_errors[] = {"NO-ERROR", "SERV-FULL", "STATIC",
2122 		"FORMAT-ERR", "NO-SUCH-LLQ", "BAD-VERS", "UNKNOWN_ERR"};
2123 	const unsigned int llq_errors_num = 7;
2124 	const char* llq_opcodes[] = {"LLQ-SETUP", "LLQ-REFRESH", "LLQ-EVENT"};
2125 	const unsigned int llq_opcodes_num = 3;
2126 
2127 	uint16_t version, llq_opcode, error_code;
2128 	uint64_t llq_id;
2129 	uint32_t lease_life; /* Requested or granted life of LLQ, in seconds */
2130 
2131 	ldns_buffer_printf(output, "; Long-Lived Query:");
2132 
2133 	/* read the record */
2134 	if(len != 18) {
2135 		ldns_buffer_printf(output, " malformed LLQ ");
2136 		ldns_edns_hex_data2buffer_str(output, data, len);
2137 
2138 		return ldns_buffer_status(output);
2139 	}
2140 	version = ldns_read_uint16(data);
2141 	llq_opcode = ldns_read_uint16(data+2);
2142 	error_code = ldns_read_uint16(data+4);
2143 	memmove(&llq_id, data+6, sizeof(uint64_t));
2144 	lease_life = ldns_read_uint32(data+14);
2145 
2146 	/* print option field entires */
2147 	ldns_buffer_printf(output, "v%d ", (int)version);
2148 
2149 	if(llq_opcode < llq_opcodes_num) {
2150 		ldns_buffer_printf(output, "%s", llq_opcodes[llq_opcode]);
2151 	} else {
2152 		ldns_buffer_printf(output, "opcode %d", (int)llq_opcode);
2153 	}
2154 
2155 	if(error_code < llq_errors_num)
2156 		ldns_buffer_printf(output, " %s", llq_errors[error_code]);
2157 	else {
2158 		ldns_buffer_printf(output, " error %d", (int)error_code);
2159 	}
2160 
2161 #ifndef USE_WINSOCK
2162 	ldns_buffer_printf(output, " id %llx lease-life %lu",
2163 		(unsigned long long)llq_id, (unsigned long)lease_life);
2164 #else
2165 	ldns_buffer_printf(output, " id %I64x lease-life %lu",
2166 		(unsigned long long)llq_id, (unsigned long)lease_life);
2167 #endif
2168 	return ldns_buffer_status(output);
2169 }
2170 
2171 
2172 static ldns_status
2173 ldns_edns_ul2buffer_str(ldns_buffer* output, uint8_t* data, size_t len)
2174 {
2175 	uint32_t lease;
2176 
2177 	ldns_buffer_printf(output, "; Update Lease:");
2178 
2179 	if(len != 4) {
2180 		ldns_buffer_printf(output, " malformed UL ");
2181 		ldns_edns_hex_data2buffer_str(output, data, len);
2182 		return ldns_buffer_status(output);
2183 	}
2184 	lease = ldns_read_uint32(data);
2185 	ldns_buffer_printf(output, "lease %lu", (unsigned long)lease);
2186 
2187 	return ldns_buffer_status(output);
2188 }
2189 
2190 static ldns_status
2191 ldns_edns_nsid2buffer_str(ldns_buffer* output, uint8_t* data, size_t len)
2192 {
2193 	size_t i, printed=0;
2194 
2195 	ldns_buffer_printf(output, "; NSID:");
2196 	ldns_edns_hex_data2buffer_str(output, data, len);
2197 
2198 	/* print the human-readable text string */
2199 	for(i = 0; i < len; i++) {
2200 		if(isprint((unsigned char)data[i]) || data[i] == '\t') {
2201 			if(!printed) {
2202 				ldns_buffer_printf(output, " (");
2203 				printed = 1;
2204 			}
2205 			ldns_buffer_printf(output, "%c", (char)data[i]);
2206 		}
2207 	}
2208 	if(printed)
2209 		ldns_buffer_printf(output, ")");
2210 	return ldns_buffer_status(output);
2211 }
2212 
2213 
2214 static ldns_status
2215 ldns_edns_dau2buffer_str(ldns_buffer* output, uint8_t* data, size_t len)
2216 {
2217 	size_t i;
2218 	ldns_lookup_table *lt;
2219 
2220 	ldns_buffer_printf(output, "; DNSSEC Algorithm Understood (DAU):");
2221 
2222 	for(i = 0; i <len; i++) {
2223 		lt = ldns_lookup_by_id(ldns_algorithms, data[i]);
2224 		if (lt && lt->name) {
2225 			ldns_buffer_printf(output, " %s", lt->name);
2226 		} else {
2227 			ldns_buffer_printf(output, " ALG%u", data[i]);
2228 		}
2229 	}
2230 	return ldns_buffer_status(output);
2231 }
2232 
2233 static ldns_status
2234 ldns_edns_dhu2buffer_str(ldns_buffer* output, uint8_t* data, size_t len)
2235 {
2236 	size_t i;
2237 	ldns_lookup_table *lt;
2238 
2239 	ldns_buffer_printf(output, "; DS Hash Understood (DHU):");
2240 
2241 	for(i = 0; i < len; i++) {
2242 		lt = ldns_lookup_by_id(ldns_hashes, data[i]);
2243 		if (lt && lt->name) {
2244 			ldns_buffer_printf(output, " %s", lt->name);
2245 		} else {
2246 			ldns_buffer_printf(output, " ALG%u", data[i]);
2247 		}
2248 	}
2249 	return ldns_buffer_status(output);
2250 }
2251 
2252 static ldns_status
2253 ldns_edns_d3u2buffer_str(ldns_buffer* output, uint8_t* data, size_t len)
2254 {
2255 	size_t i;
2256 
2257 	ldns_buffer_printf(output, "; NSEC3 Hash Understood (N3U):");
2258 
2259 	for(i=0; i<len; i++) {
2260 		if(data[i] == 1) {
2261 			ldns_buffer_printf(output, " SHA1");
2262 		} else {
2263 			ldns_buffer_printf(output, " %d", (int)data[i]);
2264 		}
2265 	}
2266 	return ldns_buffer_status(output);
2267 }
2268 
2269 static ldns_status
2270 ldns_edns_subnet2buffer_str(ldns_buffer* output, uint8_t* data, size_t len)
2271 {
2272 	uint16_t family;
2273 	uint8_t source, scope;
2274 	if(len < 4) {
2275 		ldns_buffer_printf(output, "malformed subnet ");
2276 		ldns_edns_hex_data2buffer_str(output, data, len);
2277 		return ldns_buffer_status(output);
2278 	}
2279 	family = ldns_read_uint16(data);
2280 	source = data[2];
2281 	scope = data[3];
2282 	if(family == 1) {
2283 		/* IPv4 */
2284 		char buf[64];
2285 		uint8_t ip4[4];
2286 		memset(ip4, 0, sizeof(ip4));
2287 		if(len-4 > 4) {
2288 			ldns_buffer_printf(output, "trailingdata:");
2289 			ldns_edns_hex_data2buffer_str(output, data+4+4, len-4-4);
2290 			ldns_buffer_printf(output, " ");
2291 			len = 4+4;
2292 		}
2293 		memmove(ip4, data+4, len-4);
2294 		if(!inet_ntop(AF_INET, ip4, buf, (socklen_t) sizeof(buf))) {
2295 			ldns_buffer_printf(output, "ip4ntoperror ");
2296 			ldns_edns_hex_data2buffer_str(output, data+4+4, len-4-4);
2297 		} else {
2298 			ldns_buffer_printf(output, "%s", buf);
2299 		}
2300 	} else if(family == 2) {
2301 		/* IPv6 */
2302 		char buf[64];
2303 		uint8_t ip6[16];
2304 		memset(ip6, 0, sizeof(ip6));
2305 		if(len-4 > 16) {
2306 			ldns_buffer_printf(output, "trailingdata:");
2307 			ldns_edns_hex_data2buffer_str(output, data+4+16, len-4-16);
2308 			ldns_buffer_printf(output, " ");
2309 			len = 4+16;
2310 		}
2311 		memmove(ip6, data+4, len-4);
2312 #ifdef AF_INET6
2313 		if(!inet_ntop(AF_INET6, ip6, buf, (socklen_t) sizeof(buf))) {
2314 			ldns_buffer_printf(output, "ip6ntoperror ");
2315 			ldns_edns_hex_data2buffer_str(output, data+4+4, len-4-4);
2316 		} else {
2317 			ldns_buffer_printf(output, "%s", buf);
2318 		}
2319 #else
2320 		ldns_edns_hex_data2buffer_str(output,  data+4+4, len-4-4);
2321 #endif
2322 	} else {
2323 		/* unknown */
2324 		ldns_buffer_printf(output, "family %d ", (int)family);
2325 		ldns_edns_hex_data2buffer_str(output, data, len);
2326 	}
2327 	ldns_buffer_printf(output, "/%d scope /%d", (int)source, (int)scope);
2328 
2329 	return ldns_buffer_status(output);
2330 }
2331 
2332 static ldns_status
2333 ldns_edns_expire2buffer_str(ldns_buffer* output, uint8_t* data, size_t len)
2334 {
2335 
2336 	ldns_buffer_printf(output, "; EXPIRE:");
2337 
2338 	if (!(len == 0) || len == 4) {
2339 		ldns_buffer_printf(output, "malformed expire ");
2340 		ldns_edns_hex_data2buffer_str(output, data, len);
2341 
2342 		return ldns_buffer_status(output);
2343 	}
2344 
2345 	// TODO can this output be more accurate?
2346 	ldns_edns_hex_data2buffer_str(output, data, len);
2347 
2348 	return ldns_buffer_status(output);
2349 }
2350 
2351 
2352 static ldns_status
2353 ldns_edns_cookie2buffer_str(ldns_buffer* output, uint8_t* data, size_t len)
2354 {
2355 	ldns_buffer_printf(output, "; COOKIE:");
2356 
2357 	/* the size of an EDNS cookie is restricted by RFC 7873 */
2358 	if (!(len == 8 || (len >= 16 && len < 40))) {
2359 		ldns_buffer_printf(output, "malformed cookie ");
2360 		ldns_edns_hex_data2buffer_str(output, data, len);
2361 	}
2362 	ldns_edns_hex_data2buffer_str(output, data, len);
2363 
2364 	return ldns_buffer_status(output);
2365 }
2366 
2367 static ldns_status
2368 ldns_edns_keepalive2buffer_str(ldns_buffer* output, uint8_t* data, size_t len)
2369 {
2370 	uint16_t timeout;
2371 
2372 	ldns_buffer_printf(output, "; KEEPALIVE:");
2373 
2374 	if(!(len == 0 || len == 2)) {
2375 		ldns_buffer_printf(output, "malformed keepalive ");
2376 		ldns_edns_hex_data2buffer_str(output, data, len);
2377 
2378 		return ldns_buffer_status(output);
2379 	}
2380 
2381 	if(len == 0) {
2382 		ldns_buffer_printf(output, "no timeout value (only valid for client option)");
2383 	} else {
2384 		timeout = ldns_read_uint16(data);
2385 		ldns_buffer_printf(output, "timeout value in units of 100ms %u", (int)timeout);
2386 	}
2387 	return ldns_buffer_status(output);
2388 }
2389 
2390 static ldns_status
2391 ldns_edns_padding2buffer_str(ldns_buffer* output, uint8_t* data, size_t len)
2392 {
2393 	ldns_buffer_printf(output, "; PADDING: ");
2394 	ldns_edns_hex_data2buffer_str(output, data, len);
2395 
2396 	return ldns_buffer_status(output);
2397 }
2398 
2399 static ldns_status
2400 ldns_edns_chain2buffer_str(ldns_buffer* output, uint8_t* data, size_t len)
2401 {
2402 	ldns_rdf** temp = NULL;
2403 
2404 	ldns_buffer_printf(output, "; CHAIN: ");
2405 
2406 	if (ldns_str2rdf_dname(temp, (char*) data) != LDNS_STATUS_OK) {
2407 		ldns_buffer_printf(output, "malformed chain ");
2408 		ldns_edns_hex_data2buffer_str(output, data, len);
2409 
2410 		return ldns_buffer_status(output);
2411 	}
2412 
2413 	ldns_characters2buffer_str(output, len, data);
2414 
2415 	return ldns_buffer_status(output);
2416 }
2417 
2418 static ldns_status
2419 ldns_edns_key_tag2buffer_str(ldns_buffer* output, uint8_t* data, size_t len)
2420 {
2421 	size_t i;
2422 
2423 	ldns_buffer_printf(output, "; KEY TAG: ");
2424 
2425 	if(len < 2 || len % 2 != 0) {
2426 		ldns_buffer_printf(output, "malformed key tag ");
2427 		ldns_edns_hex_data2buffer_str(output, data, len);
2428 
2429 		return ldns_buffer_status(output);
2430 	}
2431 
2432 	for (i = 0; i < len; i += 2) {
2433 		uint16_t tag = ldns_read_uint16(data);
2434 
2435 		ldns_buffer_printf(output, " %hu", tag);
2436 	}
2437 
2438 	return ldns_buffer_status(output);
2439 }
2440 
2441 static ldns_status
2442 ldns_edns_ede2buffer_str(ldns_buffer* output, uint8_t* data, size_t len)
2443 {
2444 	size_t i;
2445 	uint16_t ede;
2446 	ldns_buffer_printf(output, "; EDE:");
2447 
2448 	if(len < 2) {
2449 		ldns_buffer_printf(output, "malformed ede ");
2450 		ldns_edns_hex_data2buffer_str(output, data, len);
2451 
2452 		return ldns_buffer_status(output);
2453 	}
2454 
2455 	ede = ldns_read_uint16(data);
2456 
2457 	switch (ede) {
2458 	case LDNS_EDE_OTHER:
2459 		ldns_buffer_printf(output, " 0 (Other): ");
2460 		break;
2461 	case LDNS_EDE_UNSUPPORTED_DNSKEY_ALG:
2462 		ldns_buffer_printf(output, " 1 (Unsupported DNSKEY Algorithm)");
2463 		break;
2464 	case LDNS_EDE_UNSUPPORTED_DS_DIGEST:
2465 		ldns_buffer_printf(output, " 2 (Unsupported DS Digest type)");
2466 		break;
2467 	case LDNS_EDE_STALE_ANSWER:
2468 		ldns_buffer_printf(output, " 3 (Stale Answer)");
2469 		break;
2470 	case LDNS_EDE_FORGED_ANSWER:
2471 		ldns_buffer_printf(output, " 4 (Forged Answer)");
2472 		break;
2473 	case LDNS_EDE_DNSSEC_INDETERMINATE:
2474 		ldns_buffer_printf(output, " 5 (DNSSEC Indeterminate)");
2475 		break;
2476 	case LDNS_EDE_DNSSEC_BOGUS:
2477 		ldns_buffer_printf(output, " 6 (DNSSEC Bogus)");
2478 		break;
2479 	case LDNS_EDE_SIGNATURE_EXPIRED:
2480 		ldns_buffer_printf(output, " 7 (Signature Expired)");
2481 		break;
2482 	case LDNS_EDE_SIGNATURE_NOT_YET_VALID:
2483 		ldns_buffer_printf(output, " 8 (Signature Not Yet Valid)");
2484 		break;
2485 	case LDNS_EDE_DNSKEY_MISSING:
2486 		ldns_buffer_printf(output, " 9 (DNSKEY Missing)");
2487 		break;
2488 	case LDNS_EDE_RRSIGS_MISSING:
2489 		ldns_buffer_printf(output, " 10 (RRSIGs Missing)");
2490 		break;
2491 	case LDNS_EDE_NO_ZONE_KEY_BIT_SET:
2492 		ldns_buffer_printf(output, " 11 (No Zone Key Bit Set)");
2493 		break;
2494 	case LDNS_EDE_NSEC_MISSING:
2495 		ldns_buffer_printf(output, " 12 (NSEC Missing)");
2496 		break;
2497 	case LDNS_EDE_CACHED_ERROR:
2498 		ldns_buffer_printf(output, " 13 (Cached Error)");
2499 		break;
2500 	case LDNS_EDE_NOT_READY:
2501 		ldns_buffer_printf(output, " 14 (Not Ready)");
2502 		break;
2503 	case LDNS_EDE_BLOCKED:
2504 		ldns_buffer_printf(output, " 15 (Blocked)");
2505 		break;
2506 	case LDNS_EDE_CENSORED:
2507 		ldns_buffer_printf(output, " 16 (Censored)");
2508 		break;
2509 	case LDNS_EDE_FILTERED:
2510 		ldns_buffer_printf(output, " 17 (Filtered)");
2511 		break;
2512 	case LDNS_EDE_PROHIBITED:
2513 		ldns_buffer_printf(output, " 18 (Prohibited)");
2514 		break;
2515 	case LDNS_EDE_STALE_NXDOMAIN_ANSWER:
2516 		ldns_buffer_printf(output, " 19 (NXDOMAIN Answer)");
2517 		break;
2518 	case LDNS_EDE_NOT_AUTHORITATIVE:
2519 		ldns_buffer_printf(output, " 20 (Not Authoritative)");
2520 		break;
2521 	case LDNS_EDE_NOT_SUPPORTED:
2522 		ldns_buffer_printf(output, " 21 (Not Supported)");
2523 		break;
2524 	case LDNS_EDE_NO_REACHABLE_AUTHORITY:
2525 		ldns_buffer_printf(output, " 22 (No Reachable Authority)");
2526 		break;
2527 	case LDNS_EDE_NETWORK_ERROR:
2528 		ldns_buffer_printf(output, " 23 (Network Error)");
2529 		break;
2530 	case LDNS_EDE_INVALID_DATA:
2531 		ldns_buffer_printf(output, " 24 (Invalid Data)");
2532 		break;
2533 	case LDNS_EDE_SIGNATURE_EXPIRED_BEFORE_VALID:
2534 		ldns_buffer_printf(output, " 25 (Signature Expired Before Valid)");
2535 		break;
2536 	case LDNS_EDE_TOO_EARLY:
2537 		ldns_buffer_printf(output, " 26 (Too Early)");
2538 		break;
2539 	default:
2540 		ldns_buffer_printf(output, " %02x", data[0]);
2541 		ldns_buffer_printf(output, " %02x", data[1]);
2542 		break;
2543 	}
2544 
2545 	/* skip the EDE code in the output */
2546 	data += 2;
2547 	len -= 2;
2548 
2549 	if (len > 2) {
2550 		/* format the hex bytes */
2551 		ldns_buffer_printf(output, ":");
2552 		for (i = 0; i < len; i++) {
2553 			ldns_buffer_printf(output, " %02x", data[i]);
2554 		}
2555 
2556 		/* format the human-readable string */
2557 		ldns_buffer_printf(output, " (");
2558 		ldns_characters2buffer_str(output, len, data);
2559 		ldns_buffer_printf(output, ")");
2560 	}
2561 
2562 	return ldns_buffer_status(output);
2563 }
2564 
2565 static ldns_status
2566 ldns_edns_client_tag2buffer_str(ldns_buffer* output, uint8_t* data, size_t len)
2567 {
2568 	ldns_buffer_printf(output, "; CLIENT-TAG:");
2569 
2570 	if (len > 2) {
2571 		ldns_buffer_printf(output, "malformed client-tag ");
2572 		ldns_edns_hex_data2buffer_str(output, data, len);
2573 
2574 		return ldns_buffer_status(output);
2575 	}
2576 
2577 	ldns_edns_hex_data2buffer_str(output, data, len);
2578 
2579 	return ldns_buffer_status(output);
2580 }
2581 
2582 static ldns_status
2583 ldns_edns_server_tag2buffer_str(ldns_buffer* output, uint8_t* data, size_t len)
2584 {
2585 	ldns_buffer_printf(output, "; SERVER-TAG:");
2586 
2587 	if (len > 2) {
2588 		ldns_buffer_printf(output, "malformed server-tag ");
2589 		ldns_edns_hex_data2buffer_str(output, data, len);
2590 
2591 		return ldns_buffer_status(output);
2592 	}
2593 
2594 	ldns_edns_hex_data2buffer_str(output, data, len);
2595 
2596 	return ldns_buffer_status(output);
2597 }
2598 
2599 ldns_status
2600 ldns_edns_option_list2buffer_str(ldns_buffer *output, ldns_edns_option_list* edns_list)
2601 {
2602 	size_t count = ldns_edns_option_list_get_count(edns_list);
2603 	size_t i, size;
2604 	uint8_t* data;
2605 
2606 	for (i = 0; i < count; i++) {
2607 		ldns_edns_option_code code;
2608 		ldns_edns_option* edns = ldns_edns_option_list_get_option(edns_list, i);
2609 
2610 		if (!edns) {
2611 			break;
2612 		}
2613 
2614 		code = ldns_edns_get_code(edns);
2615 		size = ldns_edns_get_size(edns);
2616 		data = ldns_edns_get_data(edns);
2617 
2618 		switch(code) {
2619 		case LDNS_EDNS_LLQ:
2620 			ldns_edns_llq2buffer_str(output, data, size);
2621 			break;
2622 		case LDNS_EDNS_UL:
2623 			ldns_edns_ul2buffer_str(output, data, size);
2624 			break;
2625 		case LDNS_EDNS_NSID:
2626 			ldns_edns_nsid2buffer_str(output, data, size);
2627 			break;
2628 		case LDNS_EDNS_DAU:
2629 			ldns_edns_dau2buffer_str(output, data, size);
2630 			break;
2631 		case LDNS_EDNS_DHU:
2632 			ldns_edns_dhu2buffer_str(output, data, size);
2633 			break;
2634 		case LDNS_EDNS_N3U:
2635 			ldns_edns_d3u2buffer_str(output, data, size);
2636 			break;
2637 		case LDNS_EDNS_CLIENT_SUBNET:
2638 			ldns_edns_subnet2buffer_str(output, data, size);
2639 			break;
2640 		case LDNS_EDNS_EXPIRE:
2641 			ldns_edns_expire2buffer_str(output, data, size);
2642 			break;
2643 		case LDNS_EDNS_COOKIE:
2644 			ldns_edns_cookie2buffer_str(output, data, size);
2645 			break;
2646 		case LDNS_EDNS_KEEPALIVE:
2647 			ldns_edns_keepalive2buffer_str(output, data, size);
2648 			break;
2649 		case LDNS_EDNS_PADDING:
2650 			ldns_edns_padding2buffer_str(output, data, size);
2651 			break;
2652 		case LDNS_EDNS_CHAIN:
2653 			ldns_edns_chain2buffer_str(output, data, size);
2654 			break;
2655 		case LDNS_EDNS_KEY_TAG:
2656 			ldns_edns_key_tag2buffer_str(output, data, size);
2657 			break;
2658 		case LDNS_EDNS_EDE:
2659 			ldns_edns_ede2buffer_str(output, data, size);
2660 			break;
2661 		case LDNS_EDNS_CLIENT_TAG:
2662 			ldns_edns_client_tag2buffer_str(output, data, size);
2663 			break;
2664 		case LDNS_EDNS_SERVER_TAG:
2665 			ldns_edns_server_tag2buffer_str(output, data, size);
2666 			break;
2667 		default:
2668 			ldns_buffer_printf(output, "; OPT=%d:", code);
2669 			ldns_edns_hex_data2buffer_str(output, data, size);
2670 			break;
2671 		}
2672 		ldns_buffer_printf(output, "\n");
2673 	}
2674 
2675 	return ldns_buffer_status(output);
2676 }
2677 
2678 
2679 ldns_status
2680 ldns_pkt2buffer_str_fmt(ldns_buffer *output,
2681 		const ldns_output_format *fmt, const ldns_pkt *pkt)
2682 {
2683 	uint16_t i;
2684 	ldns_status status = LDNS_STATUS_OK;
2685 	char *tmp;
2686 	struct timeval time;
2687 	time_t time_tt;
2688 	int short_fmt = fmt && (fmt->flags & LDNS_FMT_SHORT);
2689 
2690 	if (!pkt) {
2691 		ldns_buffer_printf(output, "null");
2692 		return LDNS_STATUS_OK;
2693 	}
2694 
2695 	if (!ldns_buffer_status_ok(output)) {
2696 		return ldns_buffer_status(output);
2697 	}
2698 
2699 	if (!short_fmt) {
2700 		status = ldns_pktheader2buffer_str(output, pkt);
2701 		if (status != LDNS_STATUS_OK) {
2702 			return status;
2703 		}
2704 
2705 		ldns_buffer_printf(output, "\n");
2706 
2707 		ldns_buffer_printf(output, ";; QUESTION SECTION:\n;; ");
2708 
2709 
2710 		for (i = 0; i < ldns_pkt_qdcount(pkt); i++) {
2711 			status = ldns_rr2buffer_str_fmt(output, fmt,
2712 				       ldns_rr_list_rr(
2713 					       ldns_pkt_question(pkt), i));
2714 			if (status != LDNS_STATUS_OK) {
2715 				return status;
2716 			}
2717 		}
2718 		ldns_buffer_printf(output, "\n");
2719 
2720 		ldns_buffer_printf(output, ";; ANSWER SECTION:\n");
2721 	}
2722 	for (i = 0; i < ldns_pkt_ancount(pkt); i++) {
2723 		status = ldns_rr2buffer_str_fmt(output, fmt,
2724 			       ldns_rr_list_rr(
2725 				       ldns_pkt_answer(pkt), i));
2726 		if (status != LDNS_STATUS_OK) {
2727 			return status;
2728 		}
2729 	}
2730 	if (!short_fmt) {
2731 		ldns_buffer_printf(output, "\n");
2732 
2733 		ldns_buffer_printf(output, ";; AUTHORITY SECTION:\n");
2734 
2735 		for (i = 0; i < ldns_pkt_nscount(pkt); i++) {
2736 			status = ldns_rr2buffer_str_fmt(output, fmt,
2737 				       ldns_rr_list_rr(
2738 					       ldns_pkt_authority(pkt), i));
2739 			if (status != LDNS_STATUS_OK) {
2740 				return status;
2741 			}
2742 		}
2743 		ldns_buffer_printf(output, "\n");
2744 
2745 		ldns_buffer_printf(output, ";; ADDITIONAL SECTION:\n");
2746 		for (i = 0; i < ldns_pkt_arcount(pkt); i++) {
2747 			status = ldns_rr2buffer_str_fmt(output, fmt,
2748 				       ldns_rr_list_rr(
2749 					       ldns_pkt_additional(pkt), i));
2750 			if (status != LDNS_STATUS_OK) {
2751 				return status;
2752 			}
2753 
2754 		}
2755 		ldns_buffer_printf(output, "\n");
2756 		/* add some further fields */
2757 		ldns_buffer_printf(output, ";; Query time: %d msec\n",
2758 				ldns_pkt_querytime(pkt));
2759 		if (ldns_pkt_edns(pkt)) {
2760 			ldns_buffer_printf(output,
2761 				   ";; EDNS: version %u; flags:",
2762 				   ldns_pkt_edns_version(pkt));
2763 			if (ldns_pkt_edns_do(pkt)) {
2764 				ldns_buffer_printf(output, " do");
2765 			}
2766 			/* the extended rcode is the value set, shifted four bits,
2767 			 * and or'd with the original rcode */
2768 			if (ldns_pkt_edns_extended_rcode(pkt)) {
2769 				ldns_buffer_printf(output, " ; ext-rcode: %d",
2770 					(ldns_pkt_edns_extended_rcode(pkt) << 4 | ldns_pkt_get_rcode(pkt)));
2771 			}
2772 			ldns_buffer_printf(output, " ; udp: %u\n",
2773 					   ldns_pkt_edns_udp_size(pkt));
2774 
2775 			if (pkt->_edns_list)
2776 				ldns_edns_option_list2buffer_str(output, pkt->_edns_list);
2777 
2778 			else if (ldns_pkt_edns_data(pkt)) {
2779 				ldns_edns_option_list* edns_list;
2780 				/* parse the EDNS data into separate EDNS options
2781 				 * and add them to the list */
2782 				if ((edns_list = pkt_edns_data2edns_option_list(ldns_pkt_edns_data(pkt)))) {
2783 					ldns_edns_option_list2buffer_str(output, edns_list);
2784 					ldns_edns_option_list_deep_free(edns_list);
2785 				} else {
2786 					ldns_buffer_printf(output, ";; Data: ");
2787 					(void)ldns_rdf2buffer_str(output, ldns_pkt_edns_data(pkt));
2788 				}
2789 			}
2790 		}
2791 		if (ldns_pkt_tsig(pkt)) {
2792 			ldns_buffer_printf(output, ";; TSIG:\n;; ");
2793 			(void) ldns_rr2buffer_str_fmt(
2794 					output, fmt, ldns_pkt_tsig(pkt));
2795 			ldns_buffer_printf(output, "\n");
2796 		}
2797 		if (ldns_pkt_answerfrom(pkt)) {
2798 			tmp = ldns_rdf2str(ldns_pkt_answerfrom(pkt));
2799 			ldns_buffer_printf(output, ";; SERVER: %s\n", tmp);
2800 			LDNS_FREE(tmp);
2801 		}
2802 		time = ldns_pkt_timestamp(pkt);
2803 		time_tt = (time_t)time.tv_sec;
2804 		ldns_buffer_printf(output, ";; WHEN: %s",
2805 				(char*)ctime(&time_tt));
2806 
2807 		ldns_buffer_printf(output, ";; MSG SIZE  rcvd: %d\n",
2808 				(int)ldns_pkt_size(pkt));
2809 	}
2810 	return status;
2811 }
2812 
2813 ldns_status
2814 ldns_pkt2buffer_str(ldns_buffer *output, const ldns_pkt *pkt)
2815 {
2816 	return ldns_pkt2buffer_str_fmt(output, ldns_output_format_default, pkt);
2817 }
2818 
2819 
2820 #ifdef HAVE_SSL
2821 static ldns_status
2822 ldns_hmac_key2buffer_str(ldns_buffer *output, const ldns_key *k)
2823 {
2824 	ldns_status status;
2825 	size_t i;
2826 	ldns_rdf *b64_bignum;
2827 
2828 	ldns_buffer_printf(output, "Key: ");
2829 
2830  	i = ldns_key_hmac_size(k);
2831 	b64_bignum =  ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, ldns_key_hmac_key(k));
2832 	status = ldns_rdf2buffer_str(output, b64_bignum);
2833 	ldns_rdf_deep_free(b64_bignum);
2834 	ldns_buffer_printf(output, "\n");
2835 	return status;
2836 }
2837 #endif
2838 
2839 #if defined(HAVE_SSL) && defined(USE_GOST)
2840 static ldns_status
2841 ldns_gost_key2buffer_str(ldns_buffer *output, EVP_PKEY *p)
2842 {
2843 	unsigned char* pp = NULL;
2844 	int ret;
2845 	ldns_rdf *b64_bignum;
2846 	ldns_status status;
2847 
2848 	ldns_buffer_printf(output, "GostAsn1: ");
2849 
2850 	ret = i2d_PrivateKey(p, &pp);
2851 	b64_bignum = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, (size_t)ret, pp);
2852 	status = ldns_rdf2buffer_str(output, b64_bignum);
2853 
2854 	ldns_rdf_deep_free(b64_bignum);
2855 	OPENSSL_free(pp);
2856 	ldns_buffer_printf(output, "\n");
2857 	return status;
2858 }
2859 #endif
2860 
2861 #if defined(HAVE_SSL) && defined(USE_ED25519)
2862 static ldns_status
2863 ldns_ed25519_key2buffer_str(ldns_buffer *output, EVP_PKEY *p)
2864 {
2865 	unsigned char* pp = NULL;
2866 	int ret;
2867 	ldns_rdf *b64_bignum;
2868 	ldns_status status;
2869 
2870 	ldns_buffer_printf(output, "PrivateKey: ");
2871 
2872 	ret = i2d_PrivateKey(p, &pp);
2873 	/* 16 byte asn (302e020100300506032b657004220420) + 32byte key */
2874 	if(ret != 16 + 32) {
2875 		OPENSSL_free(pp);
2876 		return LDNS_STATUS_ERR;
2877 	}
2878 	b64_bignum = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64,
2879 		(size_t)ret-16, pp+16);
2880 	status = ldns_rdf2buffer_str(output, b64_bignum);
2881 
2882 	ldns_rdf_deep_free(b64_bignum);
2883 	OPENSSL_free(pp);
2884 	ldns_buffer_printf(output, "\n");
2885 	return status;
2886 }
2887 #endif
2888 
2889 #if defined(HAVE_SSL) && defined(USE_ED448)
2890 static ldns_status
2891 ldns_ed448_key2buffer_str(ldns_buffer *output, EVP_PKEY *p)
2892 {
2893 	unsigned char* pp = NULL;
2894 	int ret;
2895 	ldns_rdf *b64_bignum;
2896 	ldns_status status;
2897 
2898 	ldns_buffer_printf(output, "PrivateKey: ");
2899 
2900 	ret = i2d_PrivateKey(p, &pp);
2901 	/* some-ASN + 57byte key */
2902 	if(ret != 16 + 57) {
2903 		OPENSSL_free(pp);
2904 		return LDNS_STATUS_ERR;
2905 	}
2906 	b64_bignum = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64,
2907 		(size_t)ret-16, pp+16);
2908 	status = ldns_rdf2buffer_str(output, b64_bignum);
2909 
2910 	ldns_rdf_deep_free(b64_bignum);
2911 	OPENSSL_free(pp);
2912 	ldns_buffer_printf(output, "\n");
2913 	return status;
2914 }
2915 #endif
2916 
2917 #if defined(HAVE_SSL)
2918 /** print one b64 encoded bignum to a line in the keybuffer */
2919 static int
2920 ldns_print_bignum_b64_line(ldns_buffer* output, const char* label, const BIGNUM* num)
2921 {
2922 	unsigned char  *bignumbuf = LDNS_XMALLOC(unsigned char, LDNS_MAX_KEYLEN);
2923 	if(!bignumbuf) return 0;
2924 
2925 	ldns_buffer_printf(output, "%s: ", label);
2926 	if(num) {
2927 		ldns_rdf *b64_bignum = NULL;
2928 		int i = BN_bn2bin(num, bignumbuf);
2929 		if (i > LDNS_MAX_KEYLEN) {
2930 			LDNS_FREE(bignumbuf);
2931 			return 0;
2932 		}
2933 		b64_bignum =  ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, (size_t)i, bignumbuf);
2934 		if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) {
2935 			ldns_rdf_deep_free(b64_bignum);
2936 			LDNS_FREE(bignumbuf);
2937 			return 0;
2938 		}
2939 		ldns_rdf_deep_free(b64_bignum);
2940 		ldns_buffer_printf(output, "\n");
2941 	} else {
2942 		ldns_buffer_printf(output, "(Not available)\n");
2943 	}
2944 	LDNS_FREE(bignumbuf);
2945 	return 1;
2946 }
2947 #endif
2948 
2949 ldns_status
2950 ldns_key2buffer_str(ldns_buffer *output, const ldns_key *k)
2951 {
2952 	ldns_status status = LDNS_STATUS_OK;
2953 	unsigned char  *bignum;
2954 #ifdef HAVE_SSL
2955 	RSA *rsa;
2956 #ifdef USE_DSA
2957 	DSA *dsa;
2958 #endif /* USE_DSA */
2959 #endif /* HAVE_SSL */
2960 
2961 	if (!k) {
2962 		return LDNS_STATUS_ERR;
2963 	}
2964 
2965 	bignum = LDNS_XMALLOC(unsigned char, LDNS_MAX_KEYLEN);
2966 	if (!bignum) {
2967 		return LDNS_STATUS_ERR;
2968 	}
2969 
2970 	if (ldns_buffer_status_ok(output)) {
2971 #ifdef HAVE_SSL
2972 		switch(ldns_key_algorithm(k)) {
2973 			case LDNS_SIGN_RSASHA1:
2974 			case LDNS_SIGN_RSASHA1_NSEC3:
2975 			case LDNS_SIGN_RSASHA256:
2976 			case LDNS_SIGN_RSASHA512:
2977 			case LDNS_SIGN_RSAMD5:
2978 				/* copied by looking at dnssec-keygen output */
2979 				/* header */
2980 				rsa = ldns_key_rsa_key(k);
2981 
2982 				ldns_buffer_printf(output,"Private-key-format: v1.2\n");
2983 				switch(ldns_key_algorithm(k)) {
2984 				case LDNS_SIGN_RSAMD5:
2985 					ldns_buffer_printf(output,
2986 								    "Algorithm: %u (RSA)\n",
2987 								    LDNS_RSAMD5);
2988 					break;
2989 				case LDNS_SIGN_RSASHA1:
2990 					ldns_buffer_printf(output,
2991 								    "Algorithm: %u (RSASHA1)\n",
2992 								    LDNS_RSASHA1);
2993 					break;
2994 				case LDNS_SIGN_RSASHA1_NSEC3:
2995 					ldns_buffer_printf(output,
2996 								    "Algorithm: %u (RSASHA1_NSEC3)\n",
2997 								    LDNS_RSASHA1_NSEC3);
2998 					break;
2999 #ifdef USE_SHA2
3000 				case LDNS_SIGN_RSASHA256:
3001 					ldns_buffer_printf(output,
3002 								    "Algorithm: %u (RSASHA256)\n",
3003 								    LDNS_RSASHA256);
3004 					break;
3005 				case LDNS_SIGN_RSASHA512:
3006 					ldns_buffer_printf(output,
3007 								    "Algorithm: %u (RSASHA512)\n",
3008 								    LDNS_RSASHA512);
3009 					break;
3010 #endif
3011 				default:
3012 #ifdef STDERR_MSGS
3013 					fprintf(stderr, "Warning: unknown signature ");
3014 					fprintf(stderr,
3015 						   "algorithm type %u\n",
3016 						   ldns_key_algorithm(k));
3017 #endif
3018 					ldns_buffer_printf(output,
3019 								    "Algorithm: %u (Unknown)\n",
3020 								    ldns_key_algorithm(k));
3021 					break;
3022 				}
3023 
3024 				/* print to buf, convert to bin, convert to b64,
3025 				 * print to buf */
3026 
3027 #ifndef S_SPLINT_S
3028 				if(1) {
3029 					const BIGNUM *n=NULL, *e=NULL, *d=NULL,
3030 						*p=NULL, *q=NULL, *dmp1=NULL,
3031 						*dmq1=NULL, *iqmp=NULL;
3032 #if OPENSSL_VERSION_NUMBER < 0x10100000 || (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER < 0x20700000)
3033 					n = rsa->n;
3034 					e = rsa->e;
3035 					d = rsa->d;
3036 					p = rsa->p;
3037 					q = rsa->q;
3038 					dmp1 = rsa->dmp1;
3039 					dmq1 = rsa->dmq1;
3040 					iqmp = rsa->iqmp;
3041 #else
3042 					RSA_get0_key(rsa, &n, &e, &d);
3043 					RSA_get0_factors(rsa, &p, &q);
3044 					RSA_get0_crt_params(rsa, &dmp1,
3045 						&dmq1, &iqmp);
3046 #endif
3047 					if(!ldns_print_bignum_b64_line(output, "Modulus", n))
3048 						goto error;
3049 					if(!ldns_print_bignum_b64_line(output, "PublicExponent", e))
3050 						goto error;
3051 					if(!ldns_print_bignum_b64_line(output, "PrivateExponent", d))
3052 						goto error;
3053 					if(!ldns_print_bignum_b64_line(output, "Prime1", p))
3054 						goto error;
3055 					if(!ldns_print_bignum_b64_line(output, "Prime2", q))
3056 						goto error;
3057 					if(!ldns_print_bignum_b64_line(output, "Exponent1", dmp1))
3058 						goto error;
3059 					if(!ldns_print_bignum_b64_line(output, "Exponent2", dmq1))
3060 						goto error;
3061 					if(!ldns_print_bignum_b64_line(output, "Coefficient", iqmp))
3062 						goto error;
3063 				}
3064 #endif /* splint */
3065 
3066 				RSA_free(rsa);
3067 				break;
3068 #ifdef USE_DSA
3069 			case LDNS_SIGN_DSA:
3070 			case LDNS_SIGN_DSA_NSEC3:
3071 				dsa = ldns_key_dsa_key(k);
3072 
3073 				ldns_buffer_printf(output,"Private-key-format: v1.2\n");
3074 				if (ldns_key_algorithm(k) == LDNS_SIGN_DSA) {
3075 					ldns_buffer_printf(output,"Algorithm: 3 (DSA)\n");
3076 				} else if (ldns_key_algorithm(k) == LDNS_SIGN_DSA_NSEC3) {
3077 					ldns_buffer_printf(output,"Algorithm: 6 (DSA_NSEC3)\n");
3078 				}
3079 
3080 				/* print to buf, convert to bin, convert to b64,
3081 				 * print to buf */
3082 				if(1) {
3083 					const BIGNUM *p=NULL, *q=NULL, *g=NULL,
3084 						*priv_key=NULL, *pub_key=NULL;
3085 #if OPENSSL_VERSION_NUMBER < 0x10100000 || (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER < 0x20700000)
3086 #ifndef S_SPLINT_S
3087 					p = dsa->p;
3088 					q = dsa->q;
3089 					g = dsa->g;
3090 					priv_key = dsa->priv_key;
3091 					pub_key = dsa->pub_key;
3092 #endif /* splint */
3093 #else
3094 					DSA_get0_pqg(dsa, &p, &q, &g);
3095 					DSA_get0_key(dsa, &pub_key, &priv_key);
3096 #endif
3097 					if(!ldns_print_bignum_b64_line(output, "Prime(p)", p))
3098 						goto error;
3099 					if(!ldns_print_bignum_b64_line(output, "Subprime(q)", q))
3100 						goto error;
3101 					if(!ldns_print_bignum_b64_line(output, "Base(g)", g))
3102 						goto error;
3103 					if(!ldns_print_bignum_b64_line(output, "Private_value(x)", priv_key))
3104 						goto error;
3105 					if(!ldns_print_bignum_b64_line(output, "Public_value(y)", pub_key))
3106 						goto error;
3107 				}
3108 				break;
3109 #endif /* USE_DSA */
3110 			case LDNS_SIGN_ECC_GOST:
3111 				/* no format defined, use blob */
3112 #if defined(HAVE_SSL) && defined(USE_GOST)
3113 				ldns_buffer_printf(output, "Private-key-format: v1.2\n");
3114 				ldns_buffer_printf(output, "Algorithm: %d (ECC-GOST)\n", LDNS_SIGN_ECC_GOST);
3115 				status = ldns_gost_key2buffer_str(output,
3116 #ifndef S_SPLINT_S
3117 					k->_key.key
3118 #else
3119 					NULL
3120 #endif
3121 				);
3122 #else
3123 				goto error;
3124 #endif /* GOST */
3125 				break;
3126 			case LDNS_SIGN_ECDSAP256SHA256:
3127 			case LDNS_SIGN_ECDSAP384SHA384:
3128 #ifdef USE_ECDSA
3129                                 ldns_buffer_printf(output, "Private-key-format: v1.2\n");
3130 				ldns_buffer_printf(output, "Algorithm: %d (", ldns_key_algorithm(k));
3131                                 status=ldns_algorithm2buffer_str(output, (ldns_algorithm)ldns_key_algorithm(k));
3132 #ifndef S_SPLINT_S
3133 				ldns_buffer_printf(output, ")\n");
3134                                 if(k->_key.key) {
3135                                         EC_KEY* ec = EVP_PKEY_get1_EC_KEY(k->_key.key);
3136                                         const BIGNUM* b = EC_KEY_get0_private_key(ec);
3137 					if(!ldns_print_bignum_b64_line(output, "PrivateKey", b))
3138 						goto error;
3139                                         /* down reference count in EC_KEY
3140                                          * its still assigned to the PKEY */
3141                                         EC_KEY_free(ec);
3142                                 }
3143 #endif /* splint */
3144 #else
3145 				goto error;
3146 #endif /* ECDSA */
3147                                 break;
3148 #ifdef USE_ED25519
3149 			case LDNS_SIGN_ED25519:
3150                                 ldns_buffer_printf(output, "Private-key-format: v1.2\n");
3151 				ldns_buffer_printf(output, "Algorithm: %d (", ldns_key_algorithm(k));
3152                                 status=ldns_algorithm2buffer_str(output, (ldns_algorithm)ldns_key_algorithm(k));
3153 				ldns_buffer_printf(output, ")\n");
3154 				if (status) break;
3155 				status = ldns_ed25519_key2buffer_str(output,
3156 					k->_key.key);
3157 				break;
3158 #endif /* USE_ED25519 */
3159 #ifdef USE_ED448
3160 			case LDNS_SIGN_ED448:
3161                                 ldns_buffer_printf(output, "Private-key-format: v1.2\n");
3162 				ldns_buffer_printf(output, "Algorithm: %d (", ldns_key_algorithm(k));
3163                                 status=ldns_algorithm2buffer_str(output, (ldns_algorithm)ldns_key_algorithm(k));
3164 				ldns_buffer_printf(output, ")\n");
3165 				if (status) break;
3166 				status = ldns_ed448_key2buffer_str(output,
3167 					k->_key.key);
3168 				break;
3169 #endif /* USE_ED448 */
3170 			case LDNS_SIGN_HMACMD5:
3171 				/* there's not much of a format defined for TSIG */
3172 				/* It's just a binary blob, Same for all algorithms */
3173                 ldns_buffer_printf(output, "Private-key-format: v1.2\n");
3174                 ldns_buffer_printf(output, "Algorithm: 157 (HMAC_MD5)\n");
3175 				status = ldns_hmac_key2buffer_str(output, k);
3176 				break;
3177 			case LDNS_SIGN_HMACSHA1:
3178 		        ldns_buffer_printf(output, "Private-key-format: v1.2\n");
3179 		        ldns_buffer_printf(output, "Algorithm: 158 (HMAC_SHA1)\n");
3180 				status = ldns_hmac_key2buffer_str(output, k);
3181 				break;
3182 			case LDNS_SIGN_HMACSHA224:
3183 		        ldns_buffer_printf(output, "Private-key-format: v1.2\n");
3184 		        ldns_buffer_printf(output, "Algorithm: 162 (HMAC_SHA224)\n");
3185 				status = ldns_hmac_key2buffer_str(output, k);
3186 				break;
3187 			case LDNS_SIGN_HMACSHA256:
3188 		        ldns_buffer_printf(output, "Private-key-format: v1.2\n");
3189 		        ldns_buffer_printf(output, "Algorithm: 159 (HMAC_SHA256)\n");
3190 				status = ldns_hmac_key2buffer_str(output, k);
3191 				break;
3192 			case LDNS_SIGN_HMACSHA384:
3193 		        ldns_buffer_printf(output, "Private-key-format: v1.2\n");
3194 		        ldns_buffer_printf(output, "Algorithm: 164 (HMAC_SHA384)\n");
3195 				status = ldns_hmac_key2buffer_str(output, k);
3196 				break;
3197 			case LDNS_SIGN_HMACSHA512:
3198 		        ldns_buffer_printf(output, "Private-key-format: v1.2\n");
3199 		        ldns_buffer_printf(output, "Algorithm: 165 (HMAC_SHA512)\n");
3200 				status = ldns_hmac_key2buffer_str(output, k);
3201 				break;
3202 		}
3203 #endif /* HAVE_SSL */
3204 	} else {
3205 		LDNS_FREE(bignum);
3206 		return ldns_buffer_status(output);
3207 	}
3208 	LDNS_FREE(bignum);
3209 	return status;
3210 
3211 #ifdef HAVE_SSL
3212 	/* compiles warn the label isn't used */
3213 error:
3214 	LDNS_FREE(bignum);
3215 	return LDNS_STATUS_ERR;
3216 #endif /* HAVE_SSL */
3217 
3218 }
3219 
3220 /*
3221  * Zero terminate the buffer and copy data.
3222  */
3223 char *
3224 ldns_buffer2str(ldns_buffer *buffer)
3225 {
3226 	char *str;
3227 
3228 	/* check if buffer ends with \0, if not, and
3229 	   if there is space, add it */
3230 	if (*(ldns_buffer_at(buffer, ldns_buffer_position(buffer))) != 0) {
3231 		if (!ldns_buffer_reserve(buffer, 1)) {
3232 			return NULL;
3233 		}
3234 		ldns_buffer_write_char(buffer, (uint8_t) '\0');
3235 		if (!ldns_buffer_set_capacity(buffer, ldns_buffer_position(buffer))) {
3236 			return NULL;
3237 		}
3238 	}
3239 
3240 	str = strdup((const char *)ldns_buffer_begin(buffer));
3241         if(!str) {
3242                 return NULL;
3243         }
3244 	return str;
3245 }
3246 
3247 /*
3248  * Zero terminate the buffer and export data.
3249  */
3250 char *
3251 ldns_buffer_export2str(ldns_buffer *buffer)
3252 {
3253 	/* Append '\0' as string terminator */
3254 	if (! ldns_buffer_reserve(buffer, 1)) {
3255 		return NULL;
3256 	}
3257 	ldns_buffer_write_char(buffer, 0);
3258 
3259 	/* reallocate memory to the size of the string and export */
3260 	ldns_buffer_set_capacity(buffer, ldns_buffer_position(buffer));
3261 	return ldns_buffer_export(buffer);
3262 }
3263 
3264 char *
3265 ldns_rdf2str(const ldns_rdf *rdf)
3266 {
3267 	char *result = NULL;
3268 	ldns_buffer *tmp_buffer = ldns_buffer_new(LDNS_MAX_PACKETLEN);
3269 
3270 	if (!tmp_buffer) {
3271 		return NULL;
3272 	}
3273 	if (ldns_rdf2buffer_str(tmp_buffer, rdf) == LDNS_STATUS_OK) {
3274 		/* export and return string, destroy rest */
3275 		result = ldns_buffer_export2str(tmp_buffer);
3276 	}
3277 	ldns_buffer_free(tmp_buffer);
3278 	return result;
3279 }
3280 
3281 char *
3282 ldns_rr2str_fmt(const ldns_output_format *fmt, const ldns_rr *rr)
3283 {
3284 	char *result = NULL;
3285 	ldns_buffer *tmp_buffer = ldns_buffer_new(LDNS_MAX_PACKETLEN);
3286 
3287 	if (!tmp_buffer) {
3288 		return NULL;
3289 	}
3290 	if (ldns_rr2buffer_str_fmt(tmp_buffer, fmt, rr)
3291 		       	== LDNS_STATUS_OK) {
3292 		/* export and return string, destroy rest */
3293 		result = ldns_buffer_export2str(tmp_buffer);
3294 	}
3295 	ldns_buffer_free(tmp_buffer);
3296 	return result;
3297 }
3298 
3299 char *
3300 ldns_rr2str(const ldns_rr *rr)
3301 {
3302 	return ldns_rr2str_fmt(ldns_output_format_default, rr);
3303 }
3304 
3305 char *
3306 ldns_pkt2str_fmt(const ldns_output_format *fmt, const ldns_pkt *pkt)
3307 {
3308 	char *result = NULL;
3309 	ldns_buffer *tmp_buffer = ldns_buffer_new(LDNS_MAX_PACKETLEN);
3310 
3311 	if (!tmp_buffer) {
3312 		return NULL;
3313 	}
3314 	if (ldns_pkt2buffer_str_fmt(tmp_buffer, fmt, pkt)
3315 		       	== LDNS_STATUS_OK) {
3316 		/* export and return string, destroy rest */
3317 		result = ldns_buffer_export2str(tmp_buffer);
3318 	}
3319 
3320 	ldns_buffer_free(tmp_buffer);
3321 	return result;
3322 }
3323 
3324 char *
3325 ldns_pkt2str(const ldns_pkt *pkt)
3326 {
3327 	return ldns_pkt2str_fmt(ldns_output_format_default, pkt);
3328 }
3329 
3330 char *
3331 ldns_key2str(const ldns_key *k)
3332 {
3333 	char *result = NULL;
3334 	ldns_buffer *tmp_buffer = ldns_buffer_new(LDNS_MAX_PACKETLEN);
3335 
3336 	if (!tmp_buffer) {
3337 		return NULL;
3338 	}
3339 	if (ldns_key2buffer_str(tmp_buffer, k) == LDNS_STATUS_OK) {
3340 		/* export and return string, destroy rest */
3341 		result = ldns_buffer_export2str(tmp_buffer);
3342 	}
3343 	ldns_buffer_free(tmp_buffer);
3344 	return result;
3345 }
3346 
3347 char *
3348 ldns_rr_list2str_fmt(const ldns_output_format *fmt, const ldns_rr_list *list)
3349 {
3350 	char *result = NULL;
3351 	ldns_buffer *tmp_buffer = ldns_buffer_new(LDNS_MAX_PACKETLEN);
3352 
3353 	if (!tmp_buffer) {
3354 		return NULL;
3355 	}
3356 	if (list) {
3357 		if (ldns_rr_list2buffer_str_fmt(
3358 				   tmp_buffer, fmt, list)
3359 			       	== LDNS_STATUS_OK) {
3360 		}
3361 	} else {
3362 		if (fmt == NULL) {
3363 			fmt = ldns_output_format_default;
3364 		}
3365 		if (fmt->flags & LDNS_COMMENT_NULLS) {
3366 			ldns_buffer_printf(tmp_buffer, "; (null)\n");
3367 		}
3368 	}
3369 
3370 	/* export and return string, destroy rest */
3371 	result = ldns_buffer_export2str(tmp_buffer);
3372 	ldns_buffer_free(tmp_buffer);
3373 	return result;
3374 }
3375 
3376 char *
3377 ldns_rr_list2str(const ldns_rr_list *list)
3378 {
3379 	return ldns_rr_list2str_fmt(ldns_output_format_default, list);
3380 }
3381 
3382 void
3383 ldns_rdf_print(FILE *output, const ldns_rdf *rdf)
3384 {
3385 	char *str = ldns_rdf2str(rdf);
3386 	if (str) {
3387 		fprintf(output, "%s", str);
3388 	} else {
3389 		fprintf(output, ";Unable to convert rdf to string\n");
3390 	}
3391 	LDNS_FREE(str);
3392 }
3393 
3394 void
3395 ldns_rr_print_fmt(FILE *output,
3396 		const ldns_output_format *fmt, const ldns_rr *rr)
3397 {
3398 	char *str = ldns_rr2str_fmt(fmt, rr);
3399 	if (str) {
3400 		fprintf(output, "%s", str);
3401 	} else {
3402 		fprintf(output, ";Unable to convert rr to string\n");
3403 	}
3404 	LDNS_FREE(str);
3405 }
3406 
3407 void
3408 ldns_rr_print(FILE *output, const ldns_rr *rr)
3409 {
3410 	ldns_rr_print_fmt(output, ldns_output_format_default, rr);
3411 }
3412 
3413 void
3414 ldns_pkt_print_fmt(FILE *output,
3415 		const ldns_output_format *fmt, const ldns_pkt *pkt)
3416 {
3417 	char *str = ldns_pkt2str_fmt(fmt, pkt);
3418 	if (str) {
3419 		fprintf(output, "%s", str);
3420 	} else {
3421 		fprintf(output, ";Unable to convert packet to string\n");
3422 	}
3423 	LDNS_FREE(str);
3424 }
3425 
3426 void
3427 ldns_pkt_print(FILE *output, const ldns_pkt *pkt)
3428 {
3429 	ldns_pkt_print_fmt(output, ldns_output_format_default, pkt);
3430 }
3431 
3432 void
3433 ldns_rr_list_print_fmt(FILE *output,
3434 		const ldns_output_format *fmt, const ldns_rr_list *lst)
3435 {
3436 	size_t i;
3437 	for (i = 0; i < ldns_rr_list_rr_count(lst); i++) {
3438 		ldns_rr_print_fmt(output, fmt, ldns_rr_list_rr(lst, i));
3439 	}
3440 }
3441 
3442 void
3443 ldns_rr_list_print(FILE *output, const ldns_rr_list *lst)
3444 {
3445 	ldns_rr_list_print_fmt(output, ldns_output_format_default, lst);
3446 }
3447 
3448 void
3449 ldns_resolver_print_fmt(FILE *output,
3450 		const ldns_output_format *fmt, const ldns_resolver *r)
3451 {
3452 	uint16_t i;
3453 	ldns_rdf **n;
3454 	ldns_rdf **s;
3455 	size_t *rtt;
3456 	if (!r) {
3457 		return;
3458 	}
3459 	n = ldns_resolver_nameservers(r);
3460 	s = ldns_resolver_searchlist(r);
3461 	rtt = ldns_resolver_rtt(r);
3462 
3463 	fprintf(output, "port: %d\n", (int)ldns_resolver_port(r));
3464 	fprintf(output, "edns0 size: %d\n", (int)ldns_resolver_edns_udp_size(r));
3465 	fprintf(output, "use ip6: %d\n", (int)ldns_resolver_ip6(r));
3466 
3467 	fprintf(output, "recursive: %d\n", ldns_resolver_recursive(r));
3468 	fprintf(output, "usevc: %d\n", ldns_resolver_usevc(r));
3469 	fprintf(output, "igntc: %d\n", ldns_resolver_igntc(r));
3470 	fprintf(output, "fail: %d\n", ldns_resolver_fail(r));
3471 	fprintf(output, "retry: %d\n", (int)ldns_resolver_retry(r));
3472 	fprintf(output, "retrans: %d\n", (int)ldns_resolver_retrans(r));
3473 	fprintf(output, "fallback: %d\n", ldns_resolver_fallback(r));
3474 	fprintf(output, "random: %d\n", ldns_resolver_random(r));
3475 	fprintf(output, "timeout: %d\n", (int)ldns_resolver_timeout(r).tv_sec);
3476 	fprintf(output, "dnssec: %d\n", ldns_resolver_dnssec(r));
3477 	fprintf(output, "dnssec cd: %d\n", ldns_resolver_dnssec_cd(r));
3478 	fprintf(output, "trust anchors (%d listed):\n",
3479 		(int)ldns_rr_list_rr_count(ldns_resolver_dnssec_anchors(r)));
3480 	ldns_rr_list_print_fmt(output, fmt, ldns_resolver_dnssec_anchors(r));
3481 	fprintf(output, "tsig: %s %s\n",
3482                 ldns_resolver_tsig_keyname(r)?ldns_resolver_tsig_keyname(r):"-",
3483                 ldns_resolver_tsig_algorithm(r)?ldns_resolver_tsig_algorithm(r):"-");
3484 	fprintf(output, "debug: %d\n", ldns_resolver_debug(r));
3485 
3486 	fprintf(output, "default domain: ");
3487 	ldns_rdf_print(output, ldns_resolver_domain(r));
3488 	fprintf(output, "\n");
3489 	fprintf(output, "apply default domain: %d\n", ldns_resolver_defnames(r));
3490 
3491 	fprintf(output, "searchlist (%d listed):\n",  (int)ldns_resolver_searchlist_count(r));
3492 	for (i = 0; i < ldns_resolver_searchlist_count(r); i++) {
3493 		fprintf(output, "\t");
3494 		ldns_rdf_print(output, s[i]);
3495 		fprintf(output, "\n");
3496 	}
3497 	fprintf(output, "apply search list: %d\n", ldns_resolver_dnsrch(r));
3498 
3499 	fprintf(output, "nameservers (%d listed):\n", (int)ldns_resolver_nameserver_count(r));
3500 	for (i = 0; i < ldns_resolver_nameserver_count(r); i++) {
3501 		fprintf(output, "\t");
3502 		ldns_rdf_print(output, n[i]);
3503 
3504 		switch ((int)rtt[i]) {
3505 			case LDNS_RESOLV_RTT_MIN:
3506 			fprintf(output, " - reachable\n");
3507 			break;
3508 			case LDNS_RESOLV_RTT_INF:
3509 			fprintf(output, " - unreachable\n");
3510 			break;
3511 		}
3512 	}
3513 }
3514 
3515 void
3516 ldns_resolver_print(FILE *output, const ldns_resolver *r)
3517 {
3518 	ldns_resolver_print_fmt(output, ldns_output_format_default, r);
3519 }
3520 
3521 void
3522 ldns_zone_print_fmt(FILE *output,
3523 		const ldns_output_format *fmt, const ldns_zone *z)
3524 {
3525 	if(ldns_zone_soa(z))
3526 		ldns_rr_print_fmt(output, fmt, ldns_zone_soa(z));
3527 	ldns_rr_list_print_fmt(output, fmt, ldns_zone_rrs(z));
3528 }
3529 void
3530 ldns_zone_print(FILE *output, const ldns_zone *z)
3531 {
3532 	ldns_zone_print_fmt(output, ldns_output_format_default, z);
3533 }
3534