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