xref: /dragonfly/contrib/ldns/host2str.c (revision 7ff0fc30)
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 /* lookup tables for standard DNS stuff  */
47 
48 /* Taken from RFC 2535, section 7.  */
49 ldns_lookup_table ldns_algorithms[] = {
50         { LDNS_RSAMD5, "RSAMD5" },
51         { LDNS_DH, "DH" },
52         { LDNS_DSA, "DSA" },
53         { LDNS_ECC, "ECC" },
54         { LDNS_RSASHA1, "RSASHA1" },
55         { LDNS_DSA_NSEC3, "DSA-NSEC3-SHA1" },
56         { LDNS_RSASHA1_NSEC3, "RSASHA1-NSEC3-SHA1" },
57 #ifdef USE_SHA2
58 	{ LDNS_RSASHA256, "RSASHA256"},
59 	{ LDNS_RSASHA512, "RSASHA512"},
60 #endif
61 #ifdef USE_GOST
62 	{ LDNS_ECC_GOST, "ECC-GOST"},
63 #endif
64 #ifdef USE_ECDSA
65         { LDNS_ECDSAP256SHA256, "ECDSAP256SHA256"},
66         { LDNS_ECDSAP384SHA384, "ECDSAP384SHA384"},
67 #endif
68 #ifdef USE_ED25519
69 	{ LDNS_ED25519, "ED25519"},
70 #endif
71 #ifdef USE_ED448
72 	{ LDNS_ED448, "ED448"},
73 #endif
74         { LDNS_INDIRECT, "INDIRECT" },
75         { LDNS_PRIVATEDNS, "PRIVATEDNS" },
76         { LDNS_PRIVATEOID, "PRIVATEOID" },
77         { 0, NULL }
78 };
79 
80 /* Taken from RFC 4398  */
81 ldns_lookup_table ldns_cert_algorithms[] = {
82         { LDNS_CERT_PKIX, "PKIX" },
83         { LDNS_CERT_SPKI, "SPKI" },
84         { LDNS_CERT_PGP, "PGP" },
85         { LDNS_CERT_IPKIX, "IPKIX" },
86         { LDNS_CERT_ISPKI, "ISPKI" },
87         { LDNS_CERT_IPGP, "IPGP" },
88         { LDNS_CERT_ACPKIX, "ACPKIX" },
89         { LDNS_CERT_IACPKIX, "IACPKIX" },
90         { LDNS_CERT_URI, "URI" },
91         { LDNS_CERT_OID, "OID" },
92         { 0, NULL }
93 };
94 
95 /* classes  */
96 ldns_lookup_table ldns_rr_classes[] = {
97         { LDNS_RR_CLASS_IN, "IN" },
98         { LDNS_RR_CLASS_CH, "CH" },
99         { LDNS_RR_CLASS_HS, "HS" },
100         { LDNS_RR_CLASS_NONE, "NONE" },
101         { LDNS_RR_CLASS_ANY, "ANY" },
102         { 0, NULL }
103 };
104 
105 /* if these are used elsewhere */
106 ldns_lookup_table ldns_rcodes[] = {
107         { LDNS_RCODE_NOERROR, "NOERROR" },
108         { LDNS_RCODE_FORMERR, "FORMERR" },
109         { LDNS_RCODE_SERVFAIL, "SERVFAIL" },
110         { LDNS_RCODE_NXDOMAIN, "NXDOMAIN" },
111         { LDNS_RCODE_NOTIMPL, "NOTIMPL" },
112         { LDNS_RCODE_REFUSED, "REFUSED" },
113         { LDNS_RCODE_YXDOMAIN, "YXDOMAIN" },
114         { LDNS_RCODE_YXRRSET, "YXRRSET" },
115         { LDNS_RCODE_NXRRSET, "NXRRSET" },
116         { LDNS_RCODE_NOTAUTH, "NOTAUTH" },
117         { LDNS_RCODE_NOTZONE, "NOTZONE" },
118         { 0, NULL }
119 };
120 
121 ldns_lookup_table ldns_opcodes[] = {
122         { LDNS_PACKET_QUERY, "QUERY" },
123         { LDNS_PACKET_IQUERY, "IQUERY" },
124         { LDNS_PACKET_STATUS, "STATUS" },
125 	{ LDNS_PACKET_NOTIFY, "NOTIFY" },
126 	{ LDNS_PACKET_UPDATE, "UPDATE" },
127         { 0, NULL }
128 };
129 
130 const ldns_output_format   ldns_output_format_nocomments_record = { 0, NULL };
131 const ldns_output_format  *ldns_output_format_nocomments
132 			= &ldns_output_format_nocomments_record;
133 const ldns_output_format   ldns_output_format_onlykeyids_record = {
134 	LDNS_COMMENT_KEY, NULL
135 };
136 const ldns_output_format  *ldns_output_format_onlykeyids
137 			= &ldns_output_format_onlykeyids_record;
138 const ldns_output_format  *ldns_output_format_default
139 			= &ldns_output_format_onlykeyids_record;
140 
141 const ldns_output_format   ldns_output_format_bubblebabble_record = {
142 	LDNS_COMMENT_KEY | LDNS_COMMENT_BUBBLEBABBLE | LDNS_COMMENT_FLAGS, NULL
143 };
144 const ldns_output_format  *ldns_output_format_bubblebabble
145 			= &ldns_output_format_bubblebabble_record;
146 
147 static bool
148 ldns_output_format_covers_type(const ldns_output_format* fmt, ldns_rr_type t)
149 {
150 	return fmt && (fmt->flags & LDNS_FMT_RFC3597) &&
151 		((ldns_output_format_storage*)fmt)->bitmap &&
152 		ldns_nsec_bitmap_covers_type(
153 				((ldns_output_format_storage*)fmt)->bitmap, t);
154 }
155 
156 ldns_status
157 ldns_output_format_set_type(ldns_output_format* fmt, ldns_rr_type t)
158 {
159 	ldns_output_format_storage* fmt_st = (ldns_output_format_storage*)fmt;
160 	ldns_status s;
161 
162 	assert(fmt != NULL);
163 
164 	if (!(fmt_st->flags & LDNS_FMT_RFC3597)) {
165 		ldns_output_format_set(fmt, LDNS_FMT_RFC3597);
166 	}
167 	if (! fmt_st->bitmap) {
168 		s = ldns_rdf_bitmap_known_rr_types_space(&fmt_st->bitmap);
169 		if (s != LDNS_STATUS_OK) {
170 			return s;
171 		}
172 	}
173 	return ldns_nsec_bitmap_set_type(fmt_st->bitmap, t);
174 }
175 
176 ldns_status
177 ldns_output_format_clear_type(ldns_output_format* fmt, ldns_rr_type t)
178 {
179 	ldns_output_format_storage* fmt_st = (ldns_output_format_storage*)fmt;
180 	ldns_status s;
181 
182 	assert(fmt != NULL);
183 
184 	if (!(fmt_st->flags & LDNS_FMT_RFC3597)) {
185 		ldns_output_format_set(fmt, LDNS_FMT_RFC3597);
186 	}
187 	if (! fmt_st->bitmap) {
188 		s = ldns_rdf_bitmap_known_rr_types(&fmt_st->bitmap);
189 		if (s != LDNS_STATUS_OK) {
190 			return s;
191 		}
192 	}
193 	return ldns_nsec_bitmap_clear_type(fmt_st->bitmap, t);
194 }
195 
196 ldns_status
197 ldns_pkt_opcode2buffer_str(ldns_buffer *output, ldns_pkt_opcode opcode)
198 {
199 	ldns_lookup_table *lt = ldns_lookup_by_id(ldns_opcodes, opcode);
200 	if (lt && lt->name) {
201 		ldns_buffer_printf(output, "%s", lt->name);
202 	} else {
203 		ldns_buffer_printf(output, "OPCODE%u", opcode);
204 	}
205 	return ldns_buffer_status(output);
206 }
207 
208 ldns_status
209 ldns_pkt_rcode2buffer_str(ldns_buffer *output, ldns_pkt_rcode rcode)
210 {
211 	ldns_lookup_table *lt = ldns_lookup_by_id(ldns_rcodes, rcode);
212 	if (lt && lt->name) {
213 		ldns_buffer_printf(output, "%s", lt->name);
214 	} else {
215 		ldns_buffer_printf(output, "RCODE%u", rcode);
216 	}
217 	return ldns_buffer_status(output);
218 }
219 
220 ldns_status
221 ldns_algorithm2buffer_str(ldns_buffer *output,
222                           ldns_algorithm algorithm)
223 {
224 	ldns_lookup_table *lt = ldns_lookup_by_id(ldns_algorithms,
225 	                                          algorithm);
226 	if (lt && lt->name) {
227 		ldns_buffer_printf(output, "%s", lt->name);
228 	} else {
229 		ldns_buffer_printf(output, "ALG%u", algorithm);
230 	}
231 	return ldns_buffer_status(output);
232 }
233 
234 ldns_status
235 ldns_cert_algorithm2buffer_str(ldns_buffer *output,
236                                ldns_cert_algorithm cert_algorithm)
237 {
238 	ldns_lookup_table *lt = ldns_lookup_by_id(ldns_cert_algorithms,
239 	                                          cert_algorithm);
240 	if (lt && lt->name) {
241 		ldns_buffer_printf(output, "%s", lt->name);
242 	} else {
243 		ldns_buffer_printf(output, "CERT_ALG%u",
244 		                   cert_algorithm);
245 	}
246 	return ldns_buffer_status(output);
247 }
248 
249 char *
250 ldns_pkt_opcode2str(ldns_pkt_opcode opcode)
251 {
252 	char *str;
253 	ldns_buffer *buf;
254 
255 	buf = ldns_buffer_new(12);
256 	if (!buf) {
257 		return NULL;
258 	}
259 
260 	str = NULL;
261 	if (ldns_pkt_opcode2buffer_str(buf, opcode) == LDNS_STATUS_OK) {
262 		str = ldns_buffer_export2str(buf);
263 	}
264 
265 	ldns_buffer_free(buf);
266 	return str;
267 }
268 
269 char *
270 ldns_pkt_rcode2str(ldns_pkt_rcode rcode)
271 {
272 	char *str;
273 	ldns_buffer *buf;
274 
275 	buf = ldns_buffer_new(10);
276 	if (!buf) {
277 		return NULL;
278 	}
279 
280 	str = NULL;
281 	if (ldns_pkt_rcode2buffer_str(buf, rcode) == LDNS_STATUS_OK) {
282 		str = ldns_buffer_export2str(buf);
283 	}
284 
285 	ldns_buffer_free(buf);
286 	return str;
287 }
288 
289 char *
290 ldns_pkt_algorithm2str(ldns_algorithm algorithm)
291 {
292 	char *str;
293 	ldns_buffer *buf;
294 
295 	buf = ldns_buffer_new(10);
296 	if (!buf) {
297 		return NULL;
298 	}
299 
300 	str = NULL;
301 	if (ldns_algorithm2buffer_str(buf, algorithm)
302 	    == LDNS_STATUS_OK) {
303 		str = ldns_buffer_export2str(buf);
304 	}
305 
306 	ldns_buffer_free(buf);
307 	return str;
308 }
309 
310 char *
311 ldns_pkt_cert_algorithm2str(ldns_cert_algorithm cert_algorithm)
312 {
313 	char *str;
314 	ldns_buffer *buf;
315 
316 	buf = ldns_buffer_new(10);
317 	if (!buf) {
318 		return NULL;
319 	}
320 
321 	str = NULL;
322 	if (ldns_cert_algorithm2buffer_str(buf, cert_algorithm)
323 	    == LDNS_STATUS_OK) {
324 		str = ldns_buffer_export2str(buf);
325 	}
326 
327 	ldns_buffer_free(buf);
328 	return str;
329 }
330 
331 
332 /* do NOT pass compressed data here :p */
333 ldns_status
334 ldns_rdf2buffer_str_dname(ldns_buffer *output, const ldns_rdf *dname)
335 {
336 	/* can we do with 1 pos var? or without at all? */
337 	uint8_t src_pos = 0;
338 	uint8_t len;
339 	uint8_t *data;
340 	uint8_t i;
341 	unsigned char c;
342 
343 	data = (uint8_t*)ldns_rdf_data(dname);
344 	len = data[src_pos];
345 
346 	if (ldns_rdf_size(dname) > LDNS_MAX_DOMAINLEN) {
347 		/* too large, return */
348 		return LDNS_STATUS_DOMAINNAME_OVERFLOW;
349 	}
350 
351 	/* special case: root label */
352 	if (1 == ldns_rdf_size(dname)) {
353 		ldns_buffer_printf(output, ".");
354 	} else {
355 		while ((len > 0) && src_pos < ldns_rdf_size(dname)) {
356 			src_pos++;
357 			for(i = 0; i < len; i++) {
358 				/* paranoia check for various 'strange'
359 				   characters in dnames
360 				*/
361 				c = (unsigned char) data[src_pos];
362 				if(c == '.' || c == ';' ||
363 				   c == '(' || c == ')' ||
364 				   c == '\\') {
365 					ldns_buffer_printf(output, "\\%c",
366 							data[src_pos]);
367 				} else if (!(isascii(c) && isgraph(c))) {
368 					ldns_buffer_printf(output, "\\%03u",
369 						        data[src_pos]);
370 				} else {
371 					ldns_buffer_printf(output, "%c", data[src_pos]);
372 				}
373 				src_pos++;
374 			}
375 
376 			if (src_pos < ldns_rdf_size(dname)) {
377 				ldns_buffer_printf(output, ".");
378 			}
379 			len = data[src_pos];
380 		}
381 	}
382 	return ldns_buffer_status(output);
383 }
384 
385 ldns_status
386 ldns_rdf2buffer_str_int8(ldns_buffer *output, const ldns_rdf *rdf)
387 {
388 	uint8_t data = ldns_rdf_data(rdf)[0];
389 	ldns_buffer_printf(output, "%lu", (unsigned long) data);
390 	return ldns_buffer_status(output);
391 }
392 
393 ldns_status
394 ldns_rdf2buffer_str_int16(ldns_buffer *output, const ldns_rdf *rdf)
395 {
396 	uint16_t data = ldns_read_uint16(ldns_rdf_data(rdf));
397 	ldns_buffer_printf(output, "%lu", (unsigned long) data);
398 	return ldns_buffer_status(output);
399 }
400 
401 ldns_status
402 ldns_rdf2buffer_str_int32(ldns_buffer *output, const ldns_rdf *rdf)
403 {
404 	uint32_t data = ldns_read_uint32(ldns_rdf_data(rdf));
405 	ldns_buffer_printf(output, "%lu", (unsigned long) data);
406 	return ldns_buffer_status(output);
407 }
408 
409 ldns_status
410 ldns_rdf2buffer_str_time(ldns_buffer *output, const ldns_rdf *rdf)
411 {
412 	/* create a YYYYMMDDHHMMSS string if possible */
413 	struct tm tm;
414 	char date_buf[16];
415 
416 	memset(&tm, 0, sizeof(tm));
417 	if (ldns_serial_arithmitics_gmtime_r(ldns_rdf2native_int32(rdf), time(NULL), &tm)
418 	    && strftime(date_buf, 15, "%Y%m%d%H%M%S", &tm)) {
419 		ldns_buffer_printf(output, "%s", date_buf);
420 	}
421 	return ldns_buffer_status(output);
422 }
423 
424 ldns_status
425 ldns_rdf2buffer_str_a(ldns_buffer *output, const ldns_rdf *rdf)
426 {
427 	char str[INET_ADDRSTRLEN];
428 
429 	if (inet_ntop(AF_INET, ldns_rdf_data(rdf), str, INET_ADDRSTRLEN)) {
430 		ldns_buffer_printf(output, "%s", str);
431 	}
432 	return ldns_buffer_status(output);
433 }
434 
435 ldns_status
436 ldns_rdf2buffer_str_aaaa(ldns_buffer *output, const ldns_rdf *rdf)
437 {
438 	char str[INET6_ADDRSTRLEN];
439 
440 	if (inet_ntop(AF_INET6, ldns_rdf_data(rdf), str, INET6_ADDRSTRLEN)) {
441 		ldns_buffer_printf(output, "%s", str);
442 	}
443 
444 	return ldns_buffer_status(output);
445 }
446 
447 static void
448 ldns_characters2buffer_str(ldns_buffer* output,
449 		size_t amount, const uint8_t* characters)
450 {
451 	uint8_t ch;
452 	while (amount > 0) {
453 		ch = *characters++;
454 		if (isprint((int)ch) || ch == '\t') {
455 			if (ch == '\"' || ch == '\\')
456 				ldns_buffer_printf(output, "\\%c", ch);
457 			else
458 				ldns_buffer_printf(output, "%c", ch);
459 		} else {
460 			ldns_buffer_printf(output, "\\%03u",
461                                 (unsigned)(uint8_t) ch);
462 		}
463 		amount--;
464 	}
465 }
466 
467 ldns_status
468 ldns_rdf2buffer_str_str(ldns_buffer *output, const ldns_rdf *rdf)
469 {
470         if(ldns_rdf_size(rdf) < 1) {
471                 return LDNS_STATUS_WIRE_RDATA_ERR;
472         }
473         if((int)ldns_rdf_size(rdf) < (int)ldns_rdf_data(rdf)[0] + 1) {
474                 return LDNS_STATUS_WIRE_RDATA_ERR;
475         }
476 	ldns_buffer_printf(output, "\"");
477 	ldns_characters2buffer_str(output,
478 			ldns_rdf_data(rdf)[0], ldns_rdf_data(rdf) + 1);
479 	ldns_buffer_printf(output, "\"");
480 	return ldns_buffer_status(output);
481 }
482 
483 ldns_status
484 ldns_rdf2buffer_str_b64(ldns_buffer *output, const ldns_rdf *rdf)
485 {
486 	size_t size;
487 	char *b64;
488 
489 	if (ldns_rdf_size(rdf) == 0) {
490 		ldns_buffer_printf(output, "0");
491 		return ldns_buffer_status(output);
492 	} else
493 		size = ldns_b64_ntop_calculate_size(ldns_rdf_size(rdf));
494 
495 	if (!(b64 = LDNS_XMALLOC(char, size)))
496 		return LDNS_STATUS_MEM_ERR;
497 
498 	if (ldns_b64_ntop(ldns_rdf_data(rdf), ldns_rdf_size(rdf), b64, size)) {
499 		ldns_buffer_printf(output, "%s", b64);
500 	}
501 	LDNS_FREE(b64);
502 	return ldns_buffer_status(output);
503 }
504 
505 ldns_status
506 ldns_rdf2buffer_str_b32_ext(ldns_buffer *output, const ldns_rdf *rdf)
507 {
508 	size_t size;
509 	char *b32;
510 	if(ldns_rdf_size(rdf) == 0)
511 		return LDNS_STATUS_OK;
512         /* remove -1 for the b32-hash-len octet */
513 	size = ldns_b32_ntop_calculate_size(ldns_rdf_size(rdf) - 1);
514         /* add one for the end nul for the string */
515 	b32 = LDNS_XMALLOC(char, size + 1);
516 	if(!b32) return LDNS_STATUS_MEM_ERR;
517 	size = (size_t) ldns_b32_ntop_extended_hex(ldns_rdf_data(rdf) + 1,
518 		ldns_rdf_size(rdf) - 1, b32, size+1);
519 	if (size > 0) {
520 		ldns_buffer_printf(output, "%s", b32);
521 	}
522 	LDNS_FREE(b32);
523 	return ldns_buffer_status(output);
524 }
525 
526 ldns_status
527 ldns_rdf2buffer_str_hex(ldns_buffer *output, const ldns_rdf *rdf)
528 {
529 	size_t i;
530 	for (i = 0; i < ldns_rdf_size(rdf); i++) {
531 		ldns_buffer_printf(output, "%02x", ldns_rdf_data(rdf)[i]);
532 	}
533 
534 	return ldns_buffer_status(output);
535 }
536 
537 static ldns_status
538 ldns_rdf2buffer_str_type_fmt(ldns_buffer *output,
539 		const ldns_output_format* fmt, const ldns_rdf *rdf)
540 {
541         uint16_t data = ldns_read_uint16(ldns_rdf_data(rdf));
542 
543 	if (! ldns_output_format_covers_type(fmt, data) &&
544 			ldns_rr_descript(data) &&
545 			ldns_rr_descript(data)->_name) {
546 
547 		ldns_buffer_printf(output, "%s",ldns_rr_descript(data)->_name);
548 	} else {
549 		ldns_buffer_printf(output, "TYPE%u", data);
550 	}
551 	return  ldns_buffer_status(output);
552 }
553 
554 ldns_status
555 ldns_rdf2buffer_str_type(ldns_buffer *output, const ldns_rdf *rdf)
556 {
557 	return ldns_rdf2buffer_str_type_fmt(output,
558 			ldns_output_format_default, rdf);
559 }
560 
561 ldns_status
562 ldns_rdf2buffer_str_class(ldns_buffer *output, const ldns_rdf *rdf)
563 {
564 	uint16_t data = ldns_read_uint16(ldns_rdf_data(rdf));
565 	ldns_lookup_table *lt;
566 
567  	lt = ldns_lookup_by_id(ldns_rr_classes, (int) data);
568 	if (lt) {
569 		ldns_buffer_printf(output, "\t%s", lt->name);
570 	} else {
571 		ldns_buffer_printf(output, "\tCLASS%d", data);
572 	}
573 	return ldns_buffer_status(output);
574 }
575 
576 ldns_status
577 ldns_rdf2buffer_str_cert_alg(ldns_buffer *output, const ldns_rdf *rdf)
578 {
579         uint16_t data = ldns_read_uint16(ldns_rdf_data(rdf));
580 	ldns_lookup_table *lt;
581  	lt = ldns_lookup_by_id(ldns_cert_algorithms, (int) data);
582 	if (lt) {
583 		ldns_buffer_printf(output, "%s", lt->name);
584 	} else {
585 		ldns_buffer_printf(output, "%d", data);
586 	}
587 	return ldns_buffer_status(output);
588 }
589 
590 ldns_status
591 ldns_rdf2buffer_str_alg(ldns_buffer *output, const ldns_rdf *rdf)
592 {
593 	return ldns_rdf2buffer_str_int8(output, rdf);
594 }
595 
596 static void
597 loc_cm_print(ldns_buffer *output, uint8_t mantissa, uint8_t exponent)
598 {
599 	uint8_t i;
600 	/* is it 0.<two digits> ? */
601 	if(exponent < 2) {
602 		if(exponent == 1)
603 			mantissa *= 10;
604 		ldns_buffer_printf(output, "0.%02ld", (long)mantissa);
605 		return;
606 	}
607 	/* always <digit><string of zeros> */
608 	ldns_buffer_printf(output, "%d", (int)mantissa);
609 	for(i=0; i<exponent-2; i++)
610 		ldns_buffer_printf(output, "0");
611 }
612 
613 ldns_status
614 ldns_rr_type2buffer_str(ldns_buffer *output, const ldns_rr_type type)
615 {
616 	const ldns_rr_descriptor *descriptor;
617 
618 	descriptor = ldns_rr_descript(type);
619 
620 	switch (type) {
621 		case LDNS_RR_TYPE_IXFR:
622 			ldns_buffer_printf(output, "IXFR");
623 			break;
624 		case LDNS_RR_TYPE_AXFR:
625 			ldns_buffer_printf(output, "AXFR");
626 			break;
627 		case LDNS_RR_TYPE_MAILA:
628 			ldns_buffer_printf(output, "MAILA");
629 			break;
630 		case LDNS_RR_TYPE_MAILB:
631 			ldns_buffer_printf(output, "MAILB");
632 			break;
633 		case LDNS_RR_TYPE_ANY:
634 			ldns_buffer_printf(output, "ANY");
635 			break;
636 		default:
637 			if (descriptor && descriptor->_name) {
638 				ldns_buffer_printf(output, "%s", descriptor->_name);
639 			} else {
640 				ldns_buffer_printf(output, "TYPE%u", type);
641 			}
642 	}
643 	return ldns_buffer_status(output);
644 }
645 
646 char *
647 ldns_rr_type2str(const ldns_rr_type type)
648 {
649 	char *str;
650 	ldns_buffer *buf;
651 
652 	buf = ldns_buffer_new(10);
653 	if (!buf) {
654 		return NULL;
655 	}
656 
657 	str = NULL;
658 	if (ldns_rr_type2buffer_str(buf, type) == LDNS_STATUS_OK) {
659 		str = ldns_buffer_export2str(buf);
660 	}
661 
662 	ldns_buffer_free(buf);
663 	return str;
664 }
665 
666 
667 ldns_status
668 ldns_rr_class2buffer_str(ldns_buffer *output,
669                          const ldns_rr_class klass)
670 {
671 	ldns_lookup_table *lt;
672 
673 	lt = ldns_lookup_by_id(ldns_rr_classes, klass);
674 	if (lt) {
675 		ldns_buffer_printf(output, "%s", lt->name);
676 	} else {
677 		ldns_buffer_printf(output, "CLASS%d", klass);
678 	}
679 	return ldns_buffer_status(output);
680 }
681 
682 char *
683 ldns_rr_class2str(const ldns_rr_class klass)
684 {
685 	ldns_buffer *buf;
686 	char *str;
687 
688 	buf = ldns_buffer_new(10);
689 	if (!buf) {
690 		return NULL;
691 	}
692 
693 	str = NULL;
694 	if (ldns_rr_class2buffer_str(buf, klass) == LDNS_STATUS_OK) {
695 		str = ldns_buffer_export2str(buf);
696 	}
697 	ldns_buffer_free(buf);
698 	return str;
699 }
700 
701 ldns_status
702 ldns_rdf2buffer_str_loc(ldns_buffer *output, const ldns_rdf *rdf)
703 {
704 	/* we could do checking (ie degrees < 90 etc)? */
705 	uint8_t version;
706 	uint8_t size;
707 	uint8_t horizontal_precision;
708 	uint8_t vertical_precision;
709 	uint32_t longitude;
710 	uint32_t latitude;
711 	uint32_t altitude;
712 	char northerness;
713 	char easterness;
714 	uint32_t h;
715 	uint32_t m;
716 	double s;
717 
718 	uint32_t equator = (uint32_t) ldns_power(2, 31);
719 
720         if(ldns_rdf_size(rdf) < 1) {
721                 return LDNS_STATUS_WIRE_RDATA_ERR;
722         }
723        	version = ldns_rdf_data(rdf)[0];
724 	if (version == 0) {
725 		if(ldns_rdf_size(rdf) < 16) {
726 			return LDNS_STATUS_WIRE_RDATA_ERR;
727 		}
728 		size = ldns_rdf_data(rdf)[1];
729 		horizontal_precision = ldns_rdf_data(rdf)[2];
730 		vertical_precision = ldns_rdf_data(rdf)[3];
731 
732 		latitude = ldns_read_uint32(&ldns_rdf_data(rdf)[4]);
733 		longitude = ldns_read_uint32(&ldns_rdf_data(rdf)[8]);
734 		altitude = ldns_read_uint32(&ldns_rdf_data(rdf)[12]);
735 
736 		if (latitude > equator) {
737 			northerness = 'N';
738 			latitude = latitude - equator;
739 		} else {
740 			northerness = 'S';
741 			latitude = equator - latitude;
742 		}
743 		h = latitude / (1000 * 60 * 60);
744 		latitude = latitude % (1000 * 60 * 60);
745 		m = latitude / (1000 * 60);
746 		latitude = latitude % (1000 * 60);
747 		s = (double) latitude / 1000.0;
748 		ldns_buffer_printf(output, "%02u %02u %0.3f %c ",
749 			h, m, s, northerness);
750 
751 		if (longitude > equator) {
752 			easterness = 'E';
753 			longitude = longitude - equator;
754 		} else {
755 			easterness = 'W';
756 			longitude = equator - longitude;
757 		}
758 		h = longitude / (1000 * 60 * 60);
759 		longitude = longitude % (1000 * 60 * 60);
760 		m = longitude / (1000 * 60);
761 		longitude = longitude % (1000 * 60);
762 		s = (double) longitude / (1000.0);
763 		ldns_buffer_printf(output, "%02u %02u %0.3f %c ",
764 			h, m, s, easterness);
765 
766 
767 		s = ((double) altitude) / 100;
768 		s -= 100000;
769 
770 		if(altitude%100 != 0)
771 			ldns_buffer_printf(output, "%.2f", s);
772 		else
773 			ldns_buffer_printf(output, "%.0f", s);
774 
775 		ldns_buffer_printf(output, "m ");
776 
777 		loc_cm_print(output, (size & 0xf0) >> 4, size & 0x0f);
778 		ldns_buffer_printf(output, "m ");
779 
780 		loc_cm_print(output, (horizontal_precision & 0xf0) >> 4,
781 			horizontal_precision & 0x0f);
782 		ldns_buffer_printf(output, "m ");
783 
784 		loc_cm_print(output, (vertical_precision & 0xf0) >> 4,
785 			vertical_precision & 0x0f);
786 		ldns_buffer_printf(output, "m");
787 
788 		return ldns_buffer_status(output);
789 	} else {
790 		return ldns_rdf2buffer_str_hex(output, rdf);
791 	}
792 }
793 
794 ldns_status
795 ldns_rdf2buffer_str_unknown(ldns_buffer *output, const ldns_rdf *rdf)
796 {
797 	ldns_buffer_printf(output, "\\# %u ", ldns_rdf_size(rdf));
798 	return ldns_rdf2buffer_str_hex(output, rdf);
799 }
800 
801 ldns_status
802 ldns_rdf2buffer_str_nsap(ldns_buffer *output, const ldns_rdf *rdf)
803 {
804 	ldns_buffer_printf(output, "0x");
805 	return ldns_rdf2buffer_str_hex(output, rdf);
806 }
807 
808 ldns_status
809 ldns_rdf2buffer_str_atma(ldns_buffer *output, const ldns_rdf *rdf)
810 {
811 	return ldns_rdf2buffer_str_hex(output, rdf);
812 }
813 
814 ldns_status
815 ldns_rdf2buffer_str_wks(ldns_buffer *output, const ldns_rdf *rdf)
816 {
817 	/* protocol, followed by bitmap of services */
818 	struct protoent *protocol;
819 	char *proto_name = NULL;
820 	uint8_t protocol_nr;
821 	struct servent *service;
822 	uint16_t current_service;
823 
824         if(ldns_rdf_size(rdf) < 1) {
825                 return LDNS_STATUS_WIRE_RDATA_ERR;
826         }
827 	protocol_nr = ldns_rdf_data(rdf)[0];
828 	protocol = getprotobynumber((int) protocol_nr);
829 	if (protocol && (protocol->p_name != NULL)) {
830 		proto_name = protocol->p_name;
831 		ldns_buffer_printf(output, "%s ", protocol->p_name);
832 	} else {
833 		ldns_buffer_printf(output, "%u ", protocol_nr);
834 	}
835 
836 #ifdef HAVE_ENDPROTOENT
837 	endprotoent();
838 #endif
839 
840 	for (current_service = 0;
841 	     current_service < (ldns_rdf_size(rdf)-1)*8; current_service++) {
842 		if (ldns_get_bit(&(ldns_rdf_data(rdf)[1]), current_service)) {
843 			service = getservbyport((int) htons(current_service),
844 			                        proto_name);
845 			if (service && service->s_name) {
846 				ldns_buffer_printf(output, "%s ", service->s_name);
847 			} else {
848 				ldns_buffer_printf(output, "%u ", current_service);
849 			}
850 #ifdef HAVE_ENDSERVENT
851 			endservent();
852 #endif
853 		}
854 	}
855 	return ldns_buffer_status(output);
856 }
857 
858 static ldns_status
859 ldns_rdf2buffer_str_nsec_fmt(ldns_buffer *output,
860 		const ldns_output_format* fmt, const ldns_rdf *rdf)
861 {
862 	/* Note: this code is duplicated in higher.c in
863 	 * ldns_nsec_type_check() function
864 	 */
865 	uint8_t window_block_nr;
866 	uint8_t bitmap_length;
867 	uint16_t type;
868 	uint16_t pos = 0;
869 	uint16_t bit_pos;
870 	uint8_t *data = ldns_rdf_data(rdf);
871 
872 	while((size_t)(pos + 2) < ldns_rdf_size(rdf)) {
873 		window_block_nr = data[pos];
874 		bitmap_length = data[pos + 1];
875 		pos += 2;
876 		if (ldns_rdf_size(rdf) < pos + bitmap_length) {
877 			return LDNS_STATUS_WIRE_RDATA_ERR;
878 		}
879 		for (bit_pos = 0; bit_pos < (bitmap_length) * 8; bit_pos++) {
880 			if (! ldns_get_bit(&data[pos], bit_pos)) {
881 				continue;
882 			}
883 			type = 256 * (uint16_t) window_block_nr + bit_pos;
884 
885 			if (! ldns_output_format_covers_type(fmt, type) &&
886 					ldns_rr_descript(type) &&
887 					ldns_rr_descript(type)->_name){
888 
889 				ldns_buffer_printf(output, "%s ",
890 						ldns_rr_descript(type)->_name);
891 			} else {
892 				ldns_buffer_printf(output, "TYPE%u ", type);
893 			}
894 		}
895 		pos += (uint16_t) bitmap_length;
896 	}
897 	return ldns_buffer_status(output);
898 }
899 
900 ldns_status
901 ldns_rdf2buffer_str_nsec(ldns_buffer *output, const ldns_rdf *rdf)
902 {
903 	return ldns_rdf2buffer_str_nsec_fmt(output,
904 			ldns_output_format_default, rdf);
905 }
906 
907 ldns_status
908 ldns_rdf2buffer_str_nsec3_salt(ldns_buffer *output, const ldns_rdf *rdf)
909 {
910 	uint8_t salt_length;
911 	uint8_t salt_pos;
912 
913 	uint8_t *data = ldns_rdf_data(rdf);
914 
915         if(ldns_rdf_size(rdf) < 1) {
916                 return LDNS_STATUS_WIRE_RDATA_ERR;
917         }
918 	salt_length = data[0];
919 	/* from now there are variable length entries so remember pos */
920 	if (salt_length == 0 || ((size_t)salt_length)+1 > ldns_rdf_size(rdf)) {
921 		ldns_buffer_printf(output, "- ");
922 	} else {
923 		for (salt_pos = 0; salt_pos < salt_length; salt_pos++) {
924 			ldns_buffer_printf(output, "%02x", data[1 + salt_pos]);
925 		}
926 		ldns_buffer_printf(output, " ");
927 	}
928 
929 	return ldns_buffer_status(output);
930 }
931 
932 ldns_status
933 ldns_rdf2buffer_str_period(ldns_buffer *output, const ldns_rdf *rdf)
934 {
935 	/* period is the number of seconds */
936 	if (ldns_rdf_size(rdf) != 4) {
937 		return LDNS_STATUS_WIRE_RDATA_ERR;
938 	}
939 	ldns_buffer_printf(output, "%u", ldns_read_uint32(ldns_rdf_data(rdf)));
940 	return ldns_buffer_status(output);
941 }
942 
943 ldns_status
944 ldns_rdf2buffer_str_tsigtime(ldns_buffer *output,const  ldns_rdf *rdf)
945 {
946 	/* tsigtime is 48 bits network order unsigned integer */
947 	uint64_t tsigtime = 0;
948 	uint8_t *data = ldns_rdf_data(rdf);
949 	uint64_t d0, d1, d2, d3, d4, d5;
950 
951 	if (ldns_rdf_size(rdf) < 6) {
952 		return LDNS_STATUS_WIRE_RDATA_ERR;
953 	}
954 	d0 = data[0]; /* cast to uint64 for shift operations */
955 	d1 = data[1];
956 	d2 = data[2];
957 	d3 = data[3];
958 	d4 = data[4];
959 	d5 = data[5];
960 	tsigtime = (d0<<40) | (d1<<32) | (d2<<24) | (d3<<16) | (d4<<8) | d5;
961 
962 	ldns_buffer_printf(output, "%llu ", (long long)tsigtime);
963 
964 	return ldns_buffer_status(output);
965 }
966 
967 ldns_status
968 ldns_rdf2buffer_str_apl(ldns_buffer *output, const ldns_rdf *rdf)
969 {
970 	uint8_t *data = ldns_rdf_data(rdf);
971 	uint16_t address_family;
972 	uint8_t prefix;
973 	bool negation;
974 	uint8_t adf_length;
975 	size_t i;
976 	size_t pos = 0;
977 
978 	while (pos < (unsigned int) ldns_rdf_size(rdf)) {
979                 if(pos + 3 >= (unsigned)ldns_rdf_size(rdf))
980                         return LDNS_STATUS_WIRE_RDATA_ERR;
981 		address_family = ldns_read_uint16(&data[pos]);
982 		prefix = data[pos + 2];
983 		negation = data[pos + 3] & LDNS_APL_NEGATION;
984 		adf_length = data[pos + 3] & LDNS_APL_MASK;
985 		if (address_family == LDNS_APL_IP4) {
986 			/* check if prefix < 32? */
987 			if (negation) {
988 				ldns_buffer_printf(output, "!");
989 			}
990 			ldns_buffer_printf(output, "%u:", address_family);
991 			/* address is variable length 0 - 4 */
992 			for (i = 0; i < 4; i++) {
993 				if (i > 0) {
994 					ldns_buffer_printf(output, ".");
995 				}
996 				if (i < (unsigned short) adf_length) {
997                                         if(pos+i+4 >= ldns_rdf_size(rdf))
998 					    return LDNS_STATUS_WIRE_RDATA_ERR;
999 					ldns_buffer_printf(output, "%d",
1000 					                   data[pos + i + 4]);
1001 				} else {
1002 					ldns_buffer_printf(output, "0");
1003 				}
1004 			}
1005 			ldns_buffer_printf(output, "/%u ", prefix);
1006 		} else if (address_family == LDNS_APL_IP6) {
1007 			/* check if prefix < 128? */
1008 			if (negation) {
1009 				ldns_buffer_printf(output, "!");
1010 			}
1011 			ldns_buffer_printf(output, "%u:", address_family);
1012 			/* address is variable length 0 - 16 */
1013 			for (i = 0; i < 16; i++) {
1014 				if (i % 2 == 0 && i > 0) {
1015 					ldns_buffer_printf(output, ":");
1016 				}
1017 				if (i < (unsigned short) adf_length) {
1018                                         if(pos+i+4 >= ldns_rdf_size(rdf))
1019 					    return LDNS_STATUS_WIRE_RDATA_ERR;
1020 					ldns_buffer_printf(output, "%02x",
1021 					                   data[pos + i + 4]);
1022 				} else {
1023 					ldns_buffer_printf(output, "00");
1024 				}
1025 			}
1026 			ldns_buffer_printf(output, "/%u ", prefix);
1027 
1028 		} else {
1029 			/* unknown address family */
1030 			ldns_buffer_printf(output,
1031 					"Unknown address family: %u data: ",
1032 					address_family);
1033 			for (i = 1; i < (unsigned short) (4 + adf_length); i++) {
1034                                 if(pos+i >= ldns_rdf_size(rdf))
1035                                         return LDNS_STATUS_WIRE_RDATA_ERR;
1036 				ldns_buffer_printf(output, "%02x", data[i]);
1037 			}
1038 		}
1039 		pos += 4 + adf_length;
1040 	}
1041 	return ldns_buffer_status(output);
1042 }
1043 
1044 ldns_status
1045 ldns_rdf2buffer_str_int16_data(ldns_buffer *output, const ldns_rdf *rdf)
1046 {
1047 	size_t size;
1048 	char *b64;
1049 	if (ldns_rdf_size(rdf) < 2) {
1050 		return LDNS_STATUS_WIRE_RDATA_ERR;
1051 	}
1052 	/* Subtract the size (2) of the number that specifies the length */
1053 	size = ldns_b64_ntop_calculate_size(ldns_rdf_size(rdf) - 2);
1054 	ldns_buffer_printf(output, "%u ", ldns_rdf_size(rdf) - 2);
1055 	if (ldns_rdf_size(rdf) > 2) {
1056 		b64 = LDNS_XMALLOC(char, size);
1057 		if(!b64)
1058 			return LDNS_STATUS_MEM_ERR;
1059 
1060 		if (ldns_rdf_size(rdf) > 2 &&
1061 		ldns_b64_ntop(ldns_rdf_data(rdf) + 2,
1062 					ldns_rdf_size(rdf) - 2,
1063 					b64, size)) {
1064 			ldns_buffer_printf(output, "%s", b64);
1065 		}
1066 		LDNS_FREE(b64);
1067 	}
1068 	return ldns_buffer_status(output);
1069 }
1070 
1071 ldns_status
1072 ldns_rdf2buffer_str_ipseckey(ldns_buffer *output, const ldns_rdf *rdf)
1073 {
1074 	/* wire format from
1075 	   http://www.ietf.org/internet-drafts/draft-ietf-ipseckey-rr-12.txt
1076 	*/
1077 	uint8_t *data = ldns_rdf_data(rdf);
1078 	uint8_t precedence;
1079 	uint8_t gateway_type;
1080 	uint8_t algorithm;
1081 
1082 	ldns_rdf *gateway = NULL;
1083 	uint8_t *gateway_data;
1084 
1085 	size_t public_key_size;
1086 	uint8_t *public_key_data;
1087 	ldns_rdf *public_key;
1088 
1089 	size_t offset = 0;
1090 	ldns_status status;
1091 
1092 	if (ldns_rdf_size(rdf) < 3) {
1093 		return LDNS_STATUS_WIRE_RDATA_ERR;
1094 	}
1095 	precedence = data[0];
1096 	gateway_type = data[1];
1097 	algorithm = data[2];
1098 	offset = 3;
1099 
1100 	switch (gateway_type) {
1101 		case 0:
1102 			/* no gateway */
1103 			break;
1104 		case 1:
1105 			if (ldns_rdf_size(rdf) < offset + LDNS_IP4ADDRLEN) {
1106 				return LDNS_STATUS_ERR;
1107 			}
1108 			gateway_data = LDNS_XMALLOC(uint8_t, LDNS_IP4ADDRLEN);
1109                         if(!gateway_data)
1110                                 return LDNS_STATUS_MEM_ERR;
1111 			memcpy(gateway_data, &data[offset], LDNS_IP4ADDRLEN);
1112 			gateway = ldns_rdf_new(LDNS_RDF_TYPE_A,
1113 					LDNS_IP4ADDRLEN , gateway_data);
1114 			offset += LDNS_IP4ADDRLEN;
1115                         if(!gateway) {
1116                                 LDNS_FREE(gateway_data);
1117                                 return LDNS_STATUS_MEM_ERR;
1118                         }
1119 			break;
1120 		case 2:
1121 			if (ldns_rdf_size(rdf) < offset + LDNS_IP6ADDRLEN) {
1122 				return LDNS_STATUS_ERR;
1123 			}
1124 			gateway_data = LDNS_XMALLOC(uint8_t, LDNS_IP6ADDRLEN);
1125                         if(!gateway_data)
1126                                 return LDNS_STATUS_MEM_ERR;
1127 			memcpy(gateway_data, &data[offset], LDNS_IP6ADDRLEN);
1128 			offset += LDNS_IP6ADDRLEN;
1129 			gateway =
1130 				ldns_rdf_new(LDNS_RDF_TYPE_AAAA,
1131 						LDNS_IP6ADDRLEN, gateway_data);
1132                         if(!gateway) {
1133                                 LDNS_FREE(gateway_data);
1134                                 return LDNS_STATUS_MEM_ERR;
1135                         }
1136 			break;
1137 		case 3:
1138 			status = ldns_wire2dname(&gateway, data,
1139 					ldns_rdf_size(rdf), &offset);
1140                         if(status != LDNS_STATUS_OK)
1141                                 return status;
1142 			break;
1143 		default:
1144 			/* error? */
1145 			break;
1146 	}
1147 
1148 	if (ldns_rdf_size(rdf) <= offset) {
1149                 ldns_rdf_deep_free(gateway);
1150 		return LDNS_STATUS_ERR;
1151 	}
1152 	public_key_size = ldns_rdf_size(rdf) - offset;
1153 	public_key_data = LDNS_XMALLOC(uint8_t, public_key_size);
1154         if(!public_key_data) {
1155                 ldns_rdf_deep_free(gateway);
1156                 return LDNS_STATUS_MEM_ERR;
1157         }
1158 	memcpy(public_key_data, &data[offset], public_key_size);
1159 	public_key = ldns_rdf_new(LDNS_RDF_TYPE_B64,
1160 			public_key_size, public_key_data);
1161         if(!public_key) {
1162                 LDNS_FREE(public_key_data);
1163                 ldns_rdf_deep_free(gateway);
1164                 return LDNS_STATUS_MEM_ERR;
1165         }
1166 
1167 	ldns_buffer_printf(output, "%u %u %u ", precedence, gateway_type, algorithm);
1168 	if (gateway)
1169 	  	(void) ldns_rdf2buffer_str(output, gateway);
1170 	else
1171 		ldns_buffer_printf(output, ".");
1172 	ldns_buffer_printf(output, " ");
1173 	(void) ldns_rdf2buffer_str(output, public_key);
1174 
1175 	ldns_rdf_deep_free(gateway);
1176 	ldns_rdf_deep_free(public_key);
1177 
1178 	return ldns_buffer_status(output);
1179 }
1180 
1181 ldns_status
1182 ldns_rdf2buffer_str_ilnp64(ldns_buffer *output, const ldns_rdf *rdf)
1183 {
1184 	if (ldns_rdf_size(rdf) != 8) {
1185 		return LDNS_STATUS_WIRE_RDATA_ERR;
1186 	}
1187 	ldns_buffer_printf(output,"%.4x:%.4x:%.4x:%.4x",
1188 				ldns_read_uint16(ldns_rdf_data(rdf)),
1189 				ldns_read_uint16(ldns_rdf_data(rdf)+2),
1190 				ldns_read_uint16(ldns_rdf_data(rdf)+4),
1191 				ldns_read_uint16(ldns_rdf_data(rdf)+6));
1192 	return ldns_buffer_status(output);
1193 }
1194 
1195 ldns_status
1196 ldns_rdf2buffer_str_eui48(ldns_buffer *output, const ldns_rdf *rdf)
1197 {
1198 	if (ldns_rdf_size(rdf) != 6) {
1199 		return LDNS_STATUS_WIRE_RDATA_ERR;
1200 	}
1201 	ldns_buffer_printf(output,"%.2x-%.2x-%.2x-%.2x-%.2x-%.2x",
1202 				ldns_rdf_data(rdf)[0], ldns_rdf_data(rdf)[1],
1203 				ldns_rdf_data(rdf)[2], ldns_rdf_data(rdf)[3],
1204 				ldns_rdf_data(rdf)[4], ldns_rdf_data(rdf)[5]);
1205 	return ldns_buffer_status(output);
1206 }
1207 
1208 ldns_status
1209 ldns_rdf2buffer_str_eui64(ldns_buffer *output, const ldns_rdf *rdf)
1210 {
1211 	if (ldns_rdf_size(rdf) != 8) {
1212 		return LDNS_STATUS_WIRE_RDATA_ERR;
1213 	}
1214 	ldns_buffer_printf(output,"%.2x-%.2x-%.2x-%.2x-%.2x-%.2x-%.2x-%.2x",
1215 				ldns_rdf_data(rdf)[0], ldns_rdf_data(rdf)[1],
1216 				ldns_rdf_data(rdf)[2], ldns_rdf_data(rdf)[3],
1217 				ldns_rdf_data(rdf)[4], ldns_rdf_data(rdf)[5],
1218 				ldns_rdf_data(rdf)[6], ldns_rdf_data(rdf)[7]);
1219 	return ldns_buffer_status(output);
1220 }
1221 
1222 ldns_status
1223 ldns_rdf2buffer_str_tag(ldns_buffer *output, const ldns_rdf *rdf)
1224 {
1225 	size_t nchars;
1226 	const uint8_t* chars;
1227 	char ch;
1228 	if (ldns_rdf_size(rdf) < 2) {
1229 		return LDNS_STATUS_WIRE_RDATA_ERR;
1230 	}
1231 	nchars = ldns_rdf_data(rdf)[0];
1232 	if (nchars >= ldns_rdf_size(rdf) || /* should be rdf_size - 1 */
1233 			nchars < 1) {
1234 		return LDNS_STATUS_WIRE_RDATA_ERR;
1235 	}
1236 	chars = ldns_rdf_data(rdf) + 1;
1237 	while (nchars > 0) {
1238 		ch = (char)*chars++;
1239 		if (! isalnum((unsigned char)ch)) {
1240 			return LDNS_STATUS_WIRE_RDATA_ERR;
1241 		}
1242 		ldns_buffer_printf(output, "%c", ch);
1243 		nchars--;
1244 	}
1245 	return ldns_buffer_status(output);
1246 }
1247 
1248 ldns_status
1249 ldns_rdf2buffer_str_long_str(ldns_buffer *output, const ldns_rdf *rdf)
1250 {
1251 
1252 	ldns_buffer_printf(output, "\"");
1253 	ldns_characters2buffer_str(output,
1254 			ldns_rdf_size(rdf), ldns_rdf_data(rdf));
1255 	ldns_buffer_printf(output, "\"");
1256 	return ldns_buffer_status(output);
1257 }
1258 
1259 ldns_status
1260 ldns_rdf2buffer_str_hip(ldns_buffer *output, const ldns_rdf *rdf)
1261 {
1262 	uint8_t *data = ldns_rdf_data(rdf);
1263 	size_t rdf_size = ldns_rdf_size(rdf);
1264 	uint8_t hit_size;
1265 	uint16_t pk_size;
1266 	int written;
1267 
1268 	if (rdf_size < 6) {
1269 		return LDNS_STATUS_WIRE_RDATA_ERR;
1270 	}
1271 	if ((hit_size = data[0]) == 0 ||
1272 			(pk_size = ldns_read_uint16(data + 2)) == 0 ||
1273 			rdf_size < (size_t) hit_size + pk_size + 4) {
1274 
1275 		return LDNS_STATUS_WIRE_RDATA_ERR;
1276 	}
1277 
1278 	ldns_buffer_printf(output, "%d ", (int) data[1]);
1279 
1280 	for (data += 4; hit_size > 0; hit_size--, data++) {
1281 
1282 		ldns_buffer_printf(output, "%02x", (int) *data);
1283 	}
1284 	ldns_buffer_write_u8(output, (uint8_t) ' ');
1285 
1286 	if (ldns_buffer_reserve(output,
1287 				ldns_b64_ntop_calculate_size(pk_size))) {
1288 
1289 		written = ldns_b64_ntop(data, pk_size,
1290 				(char *) ldns_buffer_current(output),
1291 				ldns_buffer_remaining(output));
1292 
1293 		if (written > 0 &&
1294 				written < (int) ldns_buffer_remaining(output)) {
1295 
1296 			output->_position += written;
1297 		}
1298 	}
1299 	return ldns_buffer_status(output);
1300 }
1301 
1302 /* implementation mimiced from ldns_rdf2buffer_str_ipseckey */
1303 ldns_status
1304 ldns_rdf2buffer_str_amtrelay(ldns_buffer *output, const ldns_rdf *rdf)
1305 {
1306 	/* wire format from
1307 	 * draft-ietf-mboned-driad-amt-discovery Section 4.2
1308 	 */
1309 	uint8_t *data = ldns_rdf_data(rdf);
1310 	uint8_t precedence;
1311 	uint8_t discovery_optional;
1312 	uint8_t relay_type;
1313 
1314 	ldns_rdf *relay = NULL;
1315 	uint8_t *relay_data;
1316 
1317 	size_t offset = 0;
1318 	ldns_status status;
1319 
1320 	if (ldns_rdf_size(rdf) < 2) {
1321 		return LDNS_STATUS_WIRE_RDATA_ERR;
1322 	}
1323 	precedence = data[0];
1324 	discovery_optional = ((data[1] & 0x80) >> 7);
1325 	relay_type = data[1] & 0x7F;
1326 	offset = 2;
1327 
1328 	switch (relay_type) {
1329 		case 0:
1330 			/* no relay */
1331 			break;
1332 		case 1:
1333 			if (ldns_rdf_size(rdf) < offset + LDNS_IP4ADDRLEN) {
1334 				return LDNS_STATUS_ERR;
1335 			}
1336 			relay_data = LDNS_XMALLOC(uint8_t, LDNS_IP4ADDRLEN);
1337                         if(!relay_data)
1338                                 return LDNS_STATUS_MEM_ERR;
1339 			memcpy(relay_data, &data[offset], LDNS_IP4ADDRLEN);
1340 			relay = ldns_rdf_new(LDNS_RDF_TYPE_A,
1341 					LDNS_IP4ADDRLEN , relay_data);
1342 			offset += LDNS_IP4ADDRLEN;
1343                         if(!relay) {
1344                                 LDNS_FREE(relay_data);
1345                                 return LDNS_STATUS_MEM_ERR;
1346                         }
1347 			break;
1348 		case 2:
1349 			if (ldns_rdf_size(rdf) < offset + LDNS_IP6ADDRLEN) {
1350 				return LDNS_STATUS_ERR;
1351 			}
1352 			relay_data = LDNS_XMALLOC(uint8_t, LDNS_IP6ADDRLEN);
1353                         if(!relay_data)
1354                                 return LDNS_STATUS_MEM_ERR;
1355 			memcpy(relay_data, &data[offset], LDNS_IP6ADDRLEN);
1356 			offset += LDNS_IP6ADDRLEN;
1357 			relay =
1358 				ldns_rdf_new(LDNS_RDF_TYPE_AAAA,
1359 						LDNS_IP6ADDRLEN, relay_data);
1360                         if(!relay) {
1361                                 LDNS_FREE(relay_data);
1362                                 return LDNS_STATUS_MEM_ERR;
1363                         }
1364 			break;
1365 		case 3:
1366 			status = ldns_wire2dname(&relay, data,
1367 					ldns_rdf_size(rdf), &offset);
1368                         if(status != LDNS_STATUS_OK)
1369                                 return status;
1370 			break;
1371 		default:
1372 			/* error? */
1373 			break;
1374 	}
1375 
1376 	if (ldns_rdf_size(rdf) != offset) {
1377                 ldns_rdf_deep_free(relay);
1378 		return LDNS_STATUS_ERR;
1379 	}
1380 	ldns_buffer_printf(output, "%u %u %u ",
1381 			precedence, discovery_optional, relay_type);
1382 	if (relay)
1383 	  	(void) ldns_rdf2buffer_str(output, relay);
1384 
1385 	ldns_rdf_deep_free(relay);
1386 	return ldns_buffer_status(output);
1387 }
1388 
1389 
1390 static ldns_status
1391 ldns_rdf2buffer_str_fmt(ldns_buffer *buffer,
1392 		const ldns_output_format* fmt, const ldns_rdf *rdf)
1393 {
1394 	ldns_status res = LDNS_STATUS_OK;
1395 
1396 	/*ldns_buffer_printf(buffer, "%u:", ldns_rdf_get_type(rdf));*/
1397 	if (rdf) {
1398 		switch(ldns_rdf_get_type(rdf)) {
1399 		case LDNS_RDF_TYPE_NONE:
1400 			break;
1401 		case LDNS_RDF_TYPE_DNAME:
1402 			res = ldns_rdf2buffer_str_dname(buffer, rdf);
1403 			break;
1404 		case LDNS_RDF_TYPE_INT8: /* Don't output mnemonics for these */
1405 		case LDNS_RDF_TYPE_ALG:
1406 		case LDNS_RDF_TYPE_CERTIFICATE_USAGE:
1407 		case LDNS_RDF_TYPE_SELECTOR:
1408 		case LDNS_RDF_TYPE_MATCHING_TYPE:
1409 			res = ldns_rdf2buffer_str_int8(buffer, rdf);
1410 			break;
1411 		case LDNS_RDF_TYPE_INT16:
1412 			res = ldns_rdf2buffer_str_int16(buffer, rdf);
1413 			break;
1414 		case LDNS_RDF_TYPE_INT32:
1415 			res = ldns_rdf2buffer_str_int32(buffer, rdf);
1416 			break;
1417 		case LDNS_RDF_TYPE_PERIOD:
1418 			res = ldns_rdf2buffer_str_period(buffer, rdf);
1419 			break;
1420 		case LDNS_RDF_TYPE_TSIGTIME:
1421 			res = ldns_rdf2buffer_str_tsigtime(buffer, rdf);
1422 			break;
1423 		case LDNS_RDF_TYPE_A:
1424 			res = ldns_rdf2buffer_str_a(buffer, rdf);
1425 			break;
1426 		case LDNS_RDF_TYPE_AAAA:
1427 			res = ldns_rdf2buffer_str_aaaa(buffer, rdf);
1428 			break;
1429 		case LDNS_RDF_TYPE_STR:
1430 			res = ldns_rdf2buffer_str_str(buffer, rdf);
1431 			break;
1432 		case LDNS_RDF_TYPE_APL:
1433 			res = ldns_rdf2buffer_str_apl(buffer, rdf);
1434 			break;
1435 		case LDNS_RDF_TYPE_B32_EXT:
1436 			res = ldns_rdf2buffer_str_b32_ext(buffer, rdf);
1437 			break;
1438 		case LDNS_RDF_TYPE_B64:
1439 			res = ldns_rdf2buffer_str_b64(buffer, rdf);
1440 			break;
1441 		case LDNS_RDF_TYPE_HEX:
1442 			res = ldns_rdf2buffer_str_hex(buffer, rdf);
1443 			break;
1444 		case LDNS_RDF_TYPE_NSEC:
1445 			res = ldns_rdf2buffer_str_nsec_fmt(buffer, fmt, rdf);
1446 			break;
1447 		case LDNS_RDF_TYPE_NSEC3_SALT:
1448 			res = ldns_rdf2buffer_str_nsec3_salt(buffer, rdf);
1449 			break;
1450 		case LDNS_RDF_TYPE_TYPE:
1451 			res = ldns_rdf2buffer_str_type_fmt(buffer, fmt, rdf);
1452 			break;
1453 		case LDNS_RDF_TYPE_CLASS:
1454 			res = ldns_rdf2buffer_str_class(buffer, rdf);
1455 			break;
1456 		case LDNS_RDF_TYPE_CERT_ALG:
1457 			res = ldns_rdf2buffer_str_cert_alg(buffer, rdf);
1458 			break;
1459 		case LDNS_RDF_TYPE_UNKNOWN:
1460 			res = ldns_rdf2buffer_str_unknown(buffer, rdf);
1461 			break;
1462 		case LDNS_RDF_TYPE_TIME:
1463 			res = ldns_rdf2buffer_str_time(buffer, rdf);
1464 			break;
1465 		case LDNS_RDF_TYPE_HIP:
1466 			res = ldns_rdf2buffer_str_hip(buffer, rdf);
1467 			break;
1468 		case LDNS_RDF_TYPE_LOC:
1469 			res = ldns_rdf2buffer_str_loc(buffer, rdf);
1470 			break;
1471 		case LDNS_RDF_TYPE_WKS:
1472 		case LDNS_RDF_TYPE_SERVICE:
1473 			res = ldns_rdf2buffer_str_wks(buffer, rdf);
1474 			break;
1475 		case LDNS_RDF_TYPE_NSAP:
1476 			res = ldns_rdf2buffer_str_nsap(buffer, rdf);
1477 			break;
1478 		case LDNS_RDF_TYPE_ATMA:
1479 			res = ldns_rdf2buffer_str_atma(buffer, rdf);
1480 			break;
1481 		case LDNS_RDF_TYPE_IPSECKEY:
1482 			res = ldns_rdf2buffer_str_ipseckey(buffer, rdf);
1483 			break;
1484 		case LDNS_RDF_TYPE_INT16_DATA:
1485 			res = ldns_rdf2buffer_str_int16_data(buffer, rdf);
1486 			break;
1487 		case LDNS_RDF_TYPE_NSEC3_NEXT_OWNER:
1488 			res = ldns_rdf2buffer_str_b32_ext(buffer, rdf);
1489 			break;
1490 		case LDNS_RDF_TYPE_ILNP64:
1491 			res = ldns_rdf2buffer_str_ilnp64(buffer, rdf);
1492 			break;
1493 		case LDNS_RDF_TYPE_EUI48:
1494 			res = ldns_rdf2buffer_str_eui48(buffer, rdf);
1495 			break;
1496 		case LDNS_RDF_TYPE_EUI64:
1497 			res = ldns_rdf2buffer_str_eui64(buffer, rdf);
1498 			break;
1499 		case LDNS_RDF_TYPE_TAG:
1500 			res = ldns_rdf2buffer_str_tag(buffer, rdf);
1501 			break;
1502 		case LDNS_RDF_TYPE_LONG_STR:
1503 			res = ldns_rdf2buffer_str_long_str(buffer, rdf);
1504 			break;
1505 		case LDNS_RDF_TYPE_AMTRELAY:
1506 			res = ldns_rdf2buffer_str_amtrelay(buffer, rdf);
1507 			break;
1508 		}
1509 	} else {
1510 		/** This will write mangled RRs */
1511 		ldns_buffer_printf(buffer, "(null) ");
1512 		res = LDNS_STATUS_ERR;
1513 	}
1514 	return res;
1515 }
1516 
1517 ldns_status
1518 ldns_rdf2buffer_str(ldns_buffer *buffer, const ldns_rdf *rdf)
1519 {
1520 	return ldns_rdf2buffer_str_fmt(buffer,ldns_output_format_default,rdf);
1521 }
1522 
1523 static ldns_rdf *
1524 ldns_b32_ext2dname(const ldns_rdf *rdf)
1525 {
1526 	size_t size;
1527 	char *b32;
1528 	ldns_rdf *out;
1529 	if(ldns_rdf_size(rdf) == 0)
1530 		return NULL;
1531         /* remove -1 for the b32-hash-len octet */
1532 	size = ldns_b32_ntop_calculate_size(ldns_rdf_size(rdf) - 1);
1533         /* add one for the end nul for the string */
1534 	b32 = LDNS_XMALLOC(char, size + 2);
1535 	if (b32) {
1536 		if (ldns_b32_ntop_extended_hex(ldns_rdf_data(rdf) + 1,
1537 				ldns_rdf_size(rdf) - 1, b32, size+1) > 0) {
1538 			b32[size] = '.';
1539 			b32[size+1] = '\0';
1540 			if (ldns_str2rdf_dname(&out, b32) == LDNS_STATUS_OK) {
1541 				LDNS_FREE(b32);
1542 				return out;
1543 			}
1544 		}
1545 		LDNS_FREE(b32);
1546 	}
1547 	return NULL;
1548 }
1549 
1550 static ldns_status
1551 ldns_rr2buffer_str_rfc3597(ldns_buffer *output, const ldns_rr *rr)
1552 {
1553 	size_t total_rdfsize = 0;
1554 	size_t i, j;
1555 
1556 	ldns_buffer_printf(output, "TYPE%u\t", ldns_rr_get_type(rr));
1557 	for (i = 0; i < ldns_rr_rd_count(rr); i++) {
1558 		total_rdfsize += ldns_rdf_size(ldns_rr_rdf(rr, i));
1559 	}
1560 	if (total_rdfsize == 0) {
1561 		ldns_buffer_printf(output, "\\# 0\n");
1562 		return ldns_buffer_status(output);
1563 	}
1564 	ldns_buffer_printf(output, "\\# %d ", total_rdfsize);
1565 	for (i = 0; i < ldns_rr_rd_count(rr); i++) {
1566 		for (j = 0; j < ldns_rdf_size(ldns_rr_rdf(rr, i)); j++) {
1567 			ldns_buffer_printf(output, "%.2x",
1568 					ldns_rdf_data(ldns_rr_rdf(rr, i))[j]);
1569 		}
1570 	}
1571 	ldns_buffer_printf(output, "\n");
1572 	return ldns_buffer_status(output);
1573 }
1574 
1575 ldns_status
1576 ldns_rr2buffer_str_fmt(ldns_buffer *output,
1577 		const ldns_output_format *fmt, const ldns_rr *rr)
1578 {
1579 	uint16_t i, flags;
1580 	ldns_status status = LDNS_STATUS_OK;
1581 	ldns_output_format_storage* fmt_st = (ldns_output_format_storage*)fmt;
1582 
1583 	if (fmt_st == NULL) {
1584 		fmt_st = (ldns_output_format_storage*)
1585 			  ldns_output_format_default;
1586 	}
1587 	if (!rr) {
1588 		if (LDNS_COMMENT_NULLS & fmt_st->flags) {
1589 			ldns_buffer_printf(output, "; (null)\n");
1590 		}
1591 		return ldns_buffer_status(output);
1592 	}
1593 	if (ldns_rr_owner(rr)) {
1594 		status = ldns_rdf2buffer_str_dname(output, ldns_rr_owner(rr));
1595 	}
1596 	if (status != LDNS_STATUS_OK) {
1597 		return status;
1598 	}
1599 
1600 	/* TTL should NOT be printed if it is a question */
1601 	if (!ldns_rr_is_question(rr)) {
1602 		ldns_buffer_printf(output, "\t%d", ldns_rr_ttl(rr));
1603 	}
1604 
1605 	ldns_buffer_printf(output, "\t");
1606 	status = ldns_rr_class2buffer_str(output, ldns_rr_get_class(rr));
1607 	if (status != LDNS_STATUS_OK) {
1608 		return status;
1609 	}
1610 	ldns_buffer_printf(output, "\t");
1611 
1612 	if (ldns_output_format_covers_type(fmt, ldns_rr_get_type(rr))) {
1613 		return ldns_rr2buffer_str_rfc3597(output, rr);
1614 	}
1615 	status = ldns_rr_type2buffer_str(output, ldns_rr_get_type(rr));
1616 	if (status != LDNS_STATUS_OK) {
1617 		return status;
1618 	}
1619 
1620 	if (ldns_rr_rd_count(rr) > 0) {
1621 		ldns_buffer_printf(output, "\t");
1622 	} else if (!ldns_rr_is_question(rr)) {
1623 		ldns_buffer_printf(output, "\t\\# 0");
1624 	}
1625 
1626 	for (i = 0; i < ldns_rr_rd_count(rr); i++) {
1627 		/* ldns_rdf2buffer_str handles NULL input fine! */
1628 		if ((fmt_st->flags & LDNS_FMT_ZEROIZE_RRSIGS) &&
1629 				(ldns_rr_get_type(rr) == LDNS_RR_TYPE_RRSIG) &&
1630 				((/* inception  */ i == 4 &&
1631 				  ldns_rdf_get_type(ldns_rr_rdf(rr, 4)) ==
1632 							LDNS_RDF_TYPE_TIME) ||
1633 				  (/* expiration */ i == 5 &&
1634 				   ldns_rdf_get_type(ldns_rr_rdf(rr, 5)) ==
1635 				   			LDNS_RDF_TYPE_TIME) ||
1636 				  (/* signature  */ i == 8 &&
1637 				   ldns_rdf_get_type(ldns_rr_rdf(rr, 8)) ==
1638 				   			LDNS_RDF_TYPE_B64))) {
1639 
1640 			ldns_buffer_printf(output, "(null)");
1641 			status = ldns_buffer_status(output);
1642 		} else if ((fmt_st->flags & LDNS_FMT_PAD_SOA_SERIAL) &&
1643 				(ldns_rr_get_type(rr) == LDNS_RR_TYPE_SOA) &&
1644 				/* serial */ i == 2 &&
1645 			 	ldns_rdf_get_type(ldns_rr_rdf(rr, 2)) ==
1646 			 				LDNS_RDF_TYPE_INT32) {
1647 			ldns_buffer_printf(output, "%10lu",
1648 				(unsigned long) ldns_read_uint32(
1649 					ldns_rdf_data(ldns_rr_rdf(rr, 2))));
1650 			status = ldns_buffer_status(output);
1651 		} else {
1652 			status = ldns_rdf2buffer_str_fmt(output,
1653 					fmt, ldns_rr_rdf(rr, i));
1654 		}
1655 		if(status != LDNS_STATUS_OK)
1656 			return status;
1657 		if (i < ldns_rr_rd_count(rr) - 1) {
1658 			ldns_buffer_printf(output, " ");
1659 		}
1660 	}
1661 	/* per RR special comments - handy for DNSSEC types */
1662 	/* check to prevent question sec. rr from
1663 	 * getting here */
1664 	if (ldns_rr_rd_count(rr) > 0) {
1665 		switch (ldns_rr_get_type(rr)) {
1666 		case LDNS_RR_TYPE_DNSKEY:
1667 			/* if ldns_rr_rd_count(rr) > 0
1668 				then ldns_rr_rdf(rr, 0) exists! */
1669 			if (! (fmt_st->flags & LDNS_COMMENT_KEY)) {
1670 				break;
1671 			}
1672 			flags = ldns_rdf2native_int16(ldns_rr_rdf(rr, 0));
1673 			ldns_buffer_printf(output, " ;{");
1674 			if (fmt_st->flags & LDNS_COMMENT_KEY_ID) {
1675 				ldns_buffer_printf(output, "id = %u",
1676 					(unsigned int) ldns_calc_keytag(rr));
1677 			}
1678 			if ((fmt_st->flags & LDNS_COMMENT_KEY_TYPE) &&
1679 					(flags & LDNS_KEY_ZONE_KEY)){
1680 
1681 				if (flags & LDNS_KEY_SEP_KEY) {
1682 					ldns_buffer_printf(output, " (ksk)");
1683 				} else {
1684 					ldns_buffer_printf(output, " (zsk)");
1685 				}
1686 				if (fmt_st->flags & LDNS_COMMENT_KEY_SIZE){
1687 					ldns_buffer_printf(output, ", ");
1688 				}
1689 			} else if (fmt_st->flags
1690 					& (LDNS_COMMENT_KEY_ID
1691 						|LDNS_COMMENT_KEY_SIZE)) {
1692 				ldns_buffer_printf( output, ", ");
1693 			}
1694 			if (fmt_st->flags & LDNS_COMMENT_KEY_SIZE) {
1695 				ldns_buffer_printf(output, "size = %db",
1696 					ldns_rr_dnskey_key_size(rr));
1697 			}
1698 			ldns_buffer_printf(output, "}");
1699 			break;
1700 		case LDNS_RR_TYPE_RRSIG:
1701 			if ((fmt_st->flags & LDNS_COMMENT_KEY)
1702 					&& (fmt_st->flags& LDNS_COMMENT_RRSIGS)
1703 					&& ldns_rr_rdf(rr, 6) != NULL) {
1704 				ldns_buffer_printf(output, " ;{id = %d}",
1705 						ldns_rdf2native_int16(
1706 							ldns_rr_rdf(rr, 6)));
1707 			}
1708 			break;
1709 		case LDNS_RR_TYPE_DS:
1710 			if ((fmt_st->flags & LDNS_COMMENT_BUBBLEBABBLE) &&
1711 					ldns_rr_rdf(rr, 3) != NULL) {
1712 
1713 				uint8_t *data = ldns_rdf_data(
1714 						ldns_rr_rdf(rr, 3));
1715 				size_t len = ldns_rdf_size(ldns_rr_rdf(rr, 3));
1716 				char *babble = ldns_bubblebabble(data, len);
1717 				if(babble) {
1718 					ldns_buffer_printf(output,
1719 							" ;{%s}", babble);
1720 				}
1721 				LDNS_FREE(babble);
1722 			}
1723 			break;
1724 		case LDNS_RR_TYPE_NSEC3:
1725 			if (! (fmt_st->flags & LDNS_COMMENT_FLAGS) &&
1726 				! (fmt_st->flags & LDNS_COMMENT_NSEC3_CHAIN)) {
1727 				break;
1728 			}
1729 			ldns_buffer_printf(output, " ;{");
1730 			if ((fmt_st->flags & LDNS_COMMENT_FLAGS)) {
1731 				if (ldns_nsec3_optout(rr)) {
1732 					ldns_buffer_printf(output,
1733 						" flags: optout");
1734 				} else {
1735 					ldns_buffer_printf(output," flags: -");
1736 				}
1737 				if (fmt_st->flags & LDNS_COMMENT_NSEC3_CHAIN &&
1738 						fmt_st->hashmap != NULL) {
1739 					ldns_buffer_printf(output, ", ");
1740 				}
1741 			}
1742 			if (fmt_st->flags & LDNS_COMMENT_NSEC3_CHAIN &&
1743 					fmt_st->hashmap != NULL) {
1744 				ldns_rbnode_t *node;
1745 				ldns_rdf *key = ldns_dname_label(
1746 						ldns_rr_owner(rr), 0);
1747 				if (key) {
1748 					node = ldns_rbtree_search(
1749 						fmt_st->hashmap,
1750 						(void *) key);
1751 					if (node->data) {
1752 						ldns_buffer_printf(output,
1753 							"from: ");
1754 						(void) ldns_rdf2buffer_str(
1755 							output,
1756 							ldns_dnssec_name_name(
1757 							   (ldns_dnssec_name*)
1758 							   node->data
1759 							));
1760 					}
1761 					ldns_rdf_free(key);
1762 				}
1763 				key = ldns_b32_ext2dname(
1764 						ldns_nsec3_next_owner(rr));
1765 				if (key) {
1766 					node = ldns_rbtree_search(
1767 						fmt_st->hashmap,
1768 						(void *) key);
1769 					if (node->data) {
1770 						ldns_buffer_printf(output,
1771 							" to: ");
1772 						(void) ldns_rdf2buffer_str(
1773 							output,
1774 							ldns_dnssec_name_name(
1775 							   (ldns_dnssec_name*)
1776 							   node->data
1777 							));
1778 					}
1779 					ldns_rdf_free(key);
1780 				}
1781 			}
1782 			ldns_buffer_printf(output, "}");
1783 			break;
1784 		default:
1785 			break;
1786 
1787 		}
1788 	}
1789 	/* last */
1790 	ldns_buffer_printf(output, "\n");
1791 	return ldns_buffer_status(output);
1792 }
1793 
1794 ldns_status
1795 ldns_rr2buffer_str(ldns_buffer *output, const ldns_rr *rr)
1796 {
1797 	return ldns_rr2buffer_str_fmt(output, ldns_output_format_default, rr);
1798 }
1799 
1800 ldns_status
1801 ldns_rr_list2buffer_str_fmt(ldns_buffer *output,
1802 		const ldns_output_format *fmt, const ldns_rr_list *list)
1803 {
1804 	uint16_t i;
1805 
1806 	for(i = 0; i < ldns_rr_list_rr_count(list); i++) {
1807 		(void) ldns_rr2buffer_str_fmt(output, fmt,
1808 				ldns_rr_list_rr(list, i));
1809 	}
1810 	return ldns_buffer_status(output);
1811 }
1812 
1813 ldns_status
1814 ldns_rr_list2buffer_str(ldns_buffer *output, const ldns_rr_list *list)
1815 {
1816 	return ldns_rr_list2buffer_str_fmt(
1817 			output, ldns_output_format_default, list);
1818 }
1819 
1820 ldns_status
1821 ldns_pktheader2buffer_str(ldns_buffer *output, const ldns_pkt *pkt)
1822 {
1823 	ldns_lookup_table *opcode = ldns_lookup_by_id(ldns_opcodes,
1824 			                    (int) ldns_pkt_get_opcode(pkt));
1825 	ldns_lookup_table *rcode = ldns_lookup_by_id(ldns_rcodes,
1826 			                    (int) ldns_pkt_get_rcode(pkt));
1827 
1828 	ldns_buffer_printf(output, ";; ->>HEADER<<- ");
1829 	if (opcode) {
1830 		ldns_buffer_printf(output, "opcode: %s, ", opcode->name);
1831 	} else {
1832 		ldns_buffer_printf(output, "opcode: ?? (%u), ",
1833 				ldns_pkt_get_opcode(pkt));
1834 	}
1835 	if (rcode) {
1836 		ldns_buffer_printf(output, "rcode: %s, ", rcode->name);
1837 	} else {
1838 		ldns_buffer_printf(output, "rcode: ?? (%u), ", ldns_pkt_get_rcode(pkt));
1839 	}
1840 	ldns_buffer_printf(output, "id: %d\n", ldns_pkt_id(pkt));
1841 	ldns_buffer_printf(output, ";; flags: ");
1842 
1843 	if (ldns_pkt_qr(pkt)) {
1844 		ldns_buffer_printf(output, "qr ");
1845 	}
1846 	if (ldns_pkt_aa(pkt)) {
1847 		ldns_buffer_printf(output, "aa ");
1848 	}
1849 	if (ldns_pkt_tc(pkt)) {
1850 		ldns_buffer_printf(output, "tc ");
1851 	}
1852 	if (ldns_pkt_rd(pkt)) {
1853 		ldns_buffer_printf(output, "rd ");
1854 	}
1855 	if (ldns_pkt_cd(pkt)) {
1856 		ldns_buffer_printf(output, "cd ");
1857 	}
1858 	if (ldns_pkt_ra(pkt)) {
1859 		ldns_buffer_printf(output, "ra ");
1860 	}
1861 	if (ldns_pkt_ad(pkt)) {
1862 		ldns_buffer_printf(output, "ad ");
1863 	}
1864 	ldns_buffer_printf(output, "; ");
1865 	ldns_buffer_printf(output, "QUERY: %u, ", ldns_pkt_qdcount(pkt));
1866 	ldns_buffer_printf(output, "ANSWER: %u, ", ldns_pkt_ancount(pkt));
1867 	ldns_buffer_printf(output, "AUTHORITY: %u, ", ldns_pkt_nscount(pkt));
1868 	ldns_buffer_printf(output, "ADDITIONAL: %u ", ldns_pkt_arcount(pkt));
1869 	return ldns_buffer_status(output);
1870 }
1871 
1872 ldns_status
1873 ldns_pkt2buffer_str_fmt(ldns_buffer *output,
1874 		const ldns_output_format *fmt, const ldns_pkt *pkt)
1875 {
1876 	uint16_t i;
1877 	ldns_status status = LDNS_STATUS_OK;
1878 	char *tmp;
1879 	struct timeval time;
1880 	time_t time_tt;
1881 
1882 	if (!pkt) {
1883 		ldns_buffer_printf(output, "null");
1884 		return LDNS_STATUS_OK;
1885 	}
1886 
1887 	if (ldns_buffer_status_ok(output)) {
1888 		status = ldns_pktheader2buffer_str(output, pkt);
1889 		if (status != LDNS_STATUS_OK) {
1890 			return status;
1891 		}
1892 
1893 		ldns_buffer_printf(output, "\n");
1894 
1895 		ldns_buffer_printf(output, ";; QUESTION SECTION:\n;; ");
1896 
1897 
1898 		for (i = 0; i < ldns_pkt_qdcount(pkt); i++) {
1899 			status = ldns_rr2buffer_str_fmt(output, fmt,
1900 				       ldns_rr_list_rr(
1901 					       ldns_pkt_question(pkt), i));
1902 			if (status != LDNS_STATUS_OK) {
1903 				return status;
1904 			}
1905 		}
1906 		ldns_buffer_printf(output, "\n");
1907 
1908 		ldns_buffer_printf(output, ";; ANSWER SECTION:\n");
1909 		for (i = 0; i < ldns_pkt_ancount(pkt); i++) {
1910 			status = ldns_rr2buffer_str_fmt(output, fmt,
1911 				       ldns_rr_list_rr(
1912 					       ldns_pkt_answer(pkt), i));
1913 			if (status != LDNS_STATUS_OK) {
1914 				return status;
1915 			}
1916 
1917 		}
1918 		ldns_buffer_printf(output, "\n");
1919 
1920 		ldns_buffer_printf(output, ";; AUTHORITY SECTION:\n");
1921 
1922 		for (i = 0; i < ldns_pkt_nscount(pkt); i++) {
1923 			status = ldns_rr2buffer_str_fmt(output, fmt,
1924 				       ldns_rr_list_rr(
1925 					       ldns_pkt_authority(pkt), i));
1926 			if (status != LDNS_STATUS_OK) {
1927 				return status;
1928 			}
1929 		}
1930 		ldns_buffer_printf(output, "\n");
1931 
1932 		ldns_buffer_printf(output, ";; ADDITIONAL SECTION:\n");
1933 		for (i = 0; i < ldns_pkt_arcount(pkt); i++) {
1934 			status = ldns_rr2buffer_str_fmt(output, fmt,
1935 				       ldns_rr_list_rr(
1936 					       ldns_pkt_additional(pkt), i));
1937 			if (status != LDNS_STATUS_OK) {
1938 				return status;
1939 			}
1940 
1941 		}
1942 		ldns_buffer_printf(output, "\n");
1943 		/* add some futher fields */
1944 		ldns_buffer_printf(output, ";; Query time: %d msec\n",
1945 				ldns_pkt_querytime(pkt));
1946 		if (ldns_pkt_edns(pkt)) {
1947 			ldns_buffer_printf(output,
1948 				   ";; EDNS: version %u; flags:",
1949 				   ldns_pkt_edns_version(pkt));
1950 			if (ldns_pkt_edns_do(pkt)) {
1951 				ldns_buffer_printf(output, " do");
1952 			}
1953 			/* the extended rcode is the value set, shifted four bits,
1954 			 * and or'd with the original rcode */
1955 			if (ldns_pkt_edns_extended_rcode(pkt)) {
1956 				ldns_buffer_printf(output, " ; ext-rcode: %d",
1957 					(ldns_pkt_edns_extended_rcode(pkt) << 4 | ldns_pkt_get_rcode(pkt)));
1958 			}
1959 			ldns_buffer_printf(output, " ; udp: %u\n",
1960 					   ldns_pkt_edns_udp_size(pkt));
1961 
1962 			if (ldns_pkt_edns_data(pkt)) {
1963 				ldns_buffer_printf(output, ";; Data: ");
1964 				(void)ldns_rdf2buffer_str(output,
1965 							  ldns_pkt_edns_data(pkt));
1966 				ldns_buffer_printf(output, "\n");
1967 			}
1968 		}
1969 		if (ldns_pkt_tsig(pkt)) {
1970 			ldns_buffer_printf(output, ";; TSIG:\n;; ");
1971 			(void) ldns_rr2buffer_str_fmt(
1972 					output, fmt, ldns_pkt_tsig(pkt));
1973 			ldns_buffer_printf(output, "\n");
1974 		}
1975 		if (ldns_pkt_answerfrom(pkt)) {
1976 			tmp = ldns_rdf2str(ldns_pkt_answerfrom(pkt));
1977 			ldns_buffer_printf(output, ";; SERVER: %s\n", tmp);
1978 			LDNS_FREE(tmp);
1979 		}
1980 		time = ldns_pkt_timestamp(pkt);
1981 		time_tt = (time_t)time.tv_sec;
1982 		ldns_buffer_printf(output, ";; WHEN: %s",
1983 				(char*)ctime(&time_tt));
1984 
1985 		ldns_buffer_printf(output, ";; MSG SIZE  rcvd: %d\n",
1986 				(int)ldns_pkt_size(pkt));
1987 	} else {
1988 		return ldns_buffer_status(output);
1989 	}
1990 	return status;
1991 }
1992 
1993 ldns_status
1994 ldns_pkt2buffer_str(ldns_buffer *output, const ldns_pkt *pkt)
1995 {
1996 	return ldns_pkt2buffer_str_fmt(output, ldns_output_format_default, pkt);
1997 }
1998 
1999 
2000 #ifdef HAVE_SSL
2001 static ldns_status
2002 ldns_hmac_key2buffer_str(ldns_buffer *output, const ldns_key *k)
2003 {
2004 	ldns_status status;
2005 	size_t i;
2006 	ldns_rdf *b64_bignum;
2007 
2008 	ldns_buffer_printf(output, "Key: ");
2009 
2010  	i = ldns_key_hmac_size(k);
2011 	b64_bignum =  ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, ldns_key_hmac_key(k));
2012 	status = ldns_rdf2buffer_str(output, b64_bignum);
2013 	ldns_rdf_deep_free(b64_bignum);
2014 	ldns_buffer_printf(output, "\n");
2015 	return status;
2016 }
2017 #endif
2018 
2019 #if defined(HAVE_SSL) && defined(USE_GOST)
2020 static ldns_status
2021 ldns_gost_key2buffer_str(ldns_buffer *output, EVP_PKEY *p)
2022 {
2023 	unsigned char* pp = NULL;
2024 	int ret;
2025 	ldns_rdf *b64_bignum;
2026 	ldns_status status;
2027 
2028 	ldns_buffer_printf(output, "GostAsn1: ");
2029 
2030 	ret = i2d_PrivateKey(p, &pp);
2031 	b64_bignum = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, (size_t)ret, pp);
2032 	status = ldns_rdf2buffer_str(output, b64_bignum);
2033 
2034 	ldns_rdf_deep_free(b64_bignum);
2035 	OPENSSL_free(pp);
2036 	ldns_buffer_printf(output, "\n");
2037 	return status;
2038 }
2039 #endif
2040 
2041 #if defined(HAVE_SSL) && defined(USE_ED25519)
2042 static ldns_status
2043 ldns_ed25519_key2buffer_str(ldns_buffer *output, EVP_PKEY *p)
2044 {
2045 	unsigned char* pp = NULL;
2046 	int ret;
2047 	ldns_rdf *b64_bignum;
2048 	ldns_status status;
2049 
2050 	ldns_buffer_printf(output, "PrivateKey: ");
2051 
2052 	ret = i2d_PrivateKey(p, &pp);
2053 	/* 16 byte asn (302e020100300506032b657004220420) + 32byte key */
2054 	if(ret != 16 + 32) {
2055 		OPENSSL_free(pp);
2056 		return LDNS_STATUS_ERR;
2057 	}
2058 	b64_bignum = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64,
2059 		(size_t)ret-16, pp+16);
2060 	status = ldns_rdf2buffer_str(output, b64_bignum);
2061 
2062 	ldns_rdf_deep_free(b64_bignum);
2063 	OPENSSL_free(pp);
2064 	ldns_buffer_printf(output, "\n");
2065 	return status;
2066 }
2067 #endif
2068 
2069 #if defined(HAVE_SSL) && defined(USE_ED448)
2070 static ldns_status
2071 ldns_ed448_key2buffer_str(ldns_buffer *output, EVP_PKEY *p)
2072 {
2073 	unsigned char* pp = NULL;
2074 	int ret;
2075 	ldns_rdf *b64_bignum;
2076 	ldns_status status;
2077 
2078 	ldns_buffer_printf(output, "PrivateKey: ");
2079 
2080 	ret = i2d_PrivateKey(p, &pp);
2081 	/* some-ASN + 57byte key */
2082 	if(ret != 16 + 57) {
2083 		OPENSSL_free(pp);
2084 		return LDNS_STATUS_ERR;
2085 	}
2086 	b64_bignum = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64,
2087 		(size_t)ret-16, pp+16);
2088 	status = ldns_rdf2buffer_str(output, b64_bignum);
2089 
2090 	ldns_rdf_deep_free(b64_bignum);
2091 	OPENSSL_free(pp);
2092 	ldns_buffer_printf(output, "\n");
2093 	return status;
2094 }
2095 #endif
2096 
2097 #if defined(HAVE_SSL)
2098 /** print one b64 encoded bignum to a line in the keybuffer */
2099 static int
2100 ldns_print_bignum_b64_line(ldns_buffer* output, const char* label, const BIGNUM* num)
2101 {
2102 	unsigned char  *bignumbuf = LDNS_XMALLOC(unsigned char, LDNS_MAX_KEYLEN);
2103 	if(!bignumbuf) return 0;
2104 
2105 	ldns_buffer_printf(output, "%s: ", label);
2106 	if(num) {
2107 		ldns_rdf *b64_bignum = NULL;
2108 		int i = BN_bn2bin(num, bignumbuf);
2109 		if (i > LDNS_MAX_KEYLEN) {
2110 			LDNS_FREE(bignumbuf);
2111 			return 0;
2112 		}
2113 		b64_bignum =  ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, (size_t)i, bignumbuf);
2114 		if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) {
2115 			ldns_rdf_deep_free(b64_bignum);
2116 			LDNS_FREE(bignumbuf);
2117 			return 0;
2118 		}
2119 		ldns_rdf_deep_free(b64_bignum);
2120 		ldns_buffer_printf(output, "\n");
2121 	} else {
2122 		ldns_buffer_printf(output, "(Not available)\n");
2123 	}
2124 	LDNS_FREE(bignumbuf);
2125 	return 1;
2126 }
2127 #endif
2128 
2129 ldns_status
2130 ldns_key2buffer_str(ldns_buffer *output, const ldns_key *k)
2131 {
2132 	ldns_status status = LDNS_STATUS_OK;
2133 	unsigned char  *bignum;
2134 #ifdef HAVE_SSL
2135 	RSA *rsa;
2136 	DSA *dsa;
2137 #endif /* HAVE_SSL */
2138 
2139 	if (!k) {
2140 		return LDNS_STATUS_ERR;
2141 	}
2142 
2143 	bignum = LDNS_XMALLOC(unsigned char, LDNS_MAX_KEYLEN);
2144 	if (!bignum) {
2145 		return LDNS_STATUS_ERR;
2146 	}
2147 
2148 	if (ldns_buffer_status_ok(output)) {
2149 #ifdef HAVE_SSL
2150 		switch(ldns_key_algorithm(k)) {
2151 			case LDNS_SIGN_RSASHA1:
2152 			case LDNS_SIGN_RSASHA1_NSEC3:
2153 			case LDNS_SIGN_RSASHA256:
2154 			case LDNS_SIGN_RSASHA512:
2155 			case LDNS_SIGN_RSAMD5:
2156 				/* copied by looking at dnssec-keygen output */
2157 				/* header */
2158 				rsa = ldns_key_rsa_key(k);
2159 
2160 				ldns_buffer_printf(output,"Private-key-format: v1.2\n");
2161 				switch(ldns_key_algorithm(k)) {
2162 				case LDNS_SIGN_RSAMD5:
2163 					ldns_buffer_printf(output,
2164 								    "Algorithm: %u (RSA)\n",
2165 								    LDNS_RSAMD5);
2166 					break;
2167 				case LDNS_SIGN_RSASHA1:
2168 					ldns_buffer_printf(output,
2169 								    "Algorithm: %u (RSASHA1)\n",
2170 								    LDNS_RSASHA1);
2171 					break;
2172 				case LDNS_SIGN_RSASHA1_NSEC3:
2173 					ldns_buffer_printf(output,
2174 								    "Algorithm: %u (RSASHA1_NSEC3)\n",
2175 								    LDNS_RSASHA1_NSEC3);
2176 					break;
2177 #ifdef USE_SHA2
2178 				case LDNS_SIGN_RSASHA256:
2179 					ldns_buffer_printf(output,
2180 								    "Algorithm: %u (RSASHA256)\n",
2181 								    LDNS_RSASHA256);
2182 					break;
2183 				case LDNS_SIGN_RSASHA512:
2184 					ldns_buffer_printf(output,
2185 								    "Algorithm: %u (RSASHA512)\n",
2186 								    LDNS_RSASHA512);
2187 					break;
2188 #endif
2189 				default:
2190 #ifdef STDERR_MSGS
2191 					fprintf(stderr, "Warning: unknown signature ");
2192 					fprintf(stderr,
2193 						   "algorithm type %u\n",
2194 						   ldns_key_algorithm(k));
2195 #endif
2196 					ldns_buffer_printf(output,
2197 								    "Algorithm: %u (Unknown)\n",
2198 								    ldns_key_algorithm(k));
2199 					break;
2200 				}
2201 
2202 				/* print to buf, convert to bin, convert to b64,
2203 				 * print to buf */
2204 
2205 #ifndef S_SPLINT_S
2206 				if(1) {
2207 					const BIGNUM *n=NULL, *e=NULL, *d=NULL,
2208 						*p=NULL, *q=NULL, *dmp1=NULL,
2209 						*dmq1=NULL, *iqmp=NULL;
2210 #if OPENSSL_VERSION_NUMBER < 0x10100000 || defined(HAVE_LIBRESSL)
2211 					n = rsa->n;
2212 					e = rsa->e;
2213 					d = rsa->d;
2214 					p = rsa->p;
2215 					q = rsa->q;
2216 					dmp1 = rsa->dmp1;
2217 					dmq1 = rsa->dmq1;
2218 					iqmp = rsa->iqmp;
2219 #else
2220 					RSA_get0_key(rsa, &n, &e, &d);
2221 					RSA_get0_factors(rsa, &p, &q);
2222 					RSA_get0_crt_params(rsa, &dmp1,
2223 						&dmq1, &iqmp);
2224 #endif
2225 					if(!ldns_print_bignum_b64_line(output, "Modulus", n))
2226 						goto error;
2227 					if(!ldns_print_bignum_b64_line(output, "PublicExponent", e))
2228 						goto error;
2229 					if(!ldns_print_bignum_b64_line(output, "PrivateExponent", d))
2230 						goto error;
2231 					if(!ldns_print_bignum_b64_line(output, "Prime1", p))
2232 						goto error;
2233 					if(!ldns_print_bignum_b64_line(output, "Prime2", q))
2234 						goto error;
2235 					if(!ldns_print_bignum_b64_line(output, "Exponent1", dmp1))
2236 						goto error;
2237 					if(!ldns_print_bignum_b64_line(output, "Exponent2", dmq1))
2238 						goto error;
2239 					if(!ldns_print_bignum_b64_line(output, "Coefficient", iqmp))
2240 						goto error;
2241 				}
2242 #endif /* splint */
2243 
2244 				RSA_free(rsa);
2245 				break;
2246 			case LDNS_SIGN_DSA:
2247 			case LDNS_SIGN_DSA_NSEC3:
2248 				dsa = ldns_key_dsa_key(k);
2249 
2250 				ldns_buffer_printf(output,"Private-key-format: v1.2\n");
2251 				if (ldns_key_algorithm(k) == LDNS_SIGN_DSA) {
2252 					ldns_buffer_printf(output,"Algorithm: 3 (DSA)\n");
2253 				} else if (ldns_key_algorithm(k) == LDNS_SIGN_DSA_NSEC3) {
2254 					ldns_buffer_printf(output,"Algorithm: 6 (DSA_NSEC3)\n");
2255 				}
2256 
2257 				/* print to buf, convert to bin, convert to b64,
2258 				 * print to buf */
2259 				if(1) {
2260 					const BIGNUM *p=NULL, *q=NULL, *g=NULL,
2261 						*priv_key=NULL, *pub_key=NULL;
2262 #if OPENSSL_VERSION_NUMBER < 0x10100000 || defined(HAVE_LIBRESSL)
2263 #ifndef S_SPLINT_S
2264 					p = dsa->p;
2265 					q = dsa->q;
2266 					g = dsa->g;
2267 					priv_key = dsa->priv_key;
2268 					pub_key = dsa->pub_key;
2269 #endif /* splint */
2270 #else
2271 					DSA_get0_pqg(dsa, &p, &q, &g);
2272 					DSA_get0_key(dsa, &pub_key, &priv_key);
2273 #endif
2274 					if(!ldns_print_bignum_b64_line(output, "Prime(p)", p))
2275 						goto error;
2276 					if(!ldns_print_bignum_b64_line(output, "Subprime(q)", q))
2277 						goto error;
2278 					if(!ldns_print_bignum_b64_line(output, "Base(g)", g))
2279 						goto error;
2280 					if(!ldns_print_bignum_b64_line(output, "Private_value(x)", priv_key))
2281 						goto error;
2282 					if(!ldns_print_bignum_b64_line(output, "Public_value(y)", pub_key))
2283 						goto error;
2284 				}
2285 				break;
2286 			case LDNS_SIGN_ECC_GOST:
2287 				/* no format defined, use blob */
2288 #if defined(HAVE_SSL) && defined(USE_GOST)
2289 				ldns_buffer_printf(output, "Private-key-format: v1.2\n");
2290 				ldns_buffer_printf(output, "Algorithm: %d (ECC-GOST)\n", LDNS_SIGN_ECC_GOST);
2291 				status = ldns_gost_key2buffer_str(output,
2292 #ifndef S_SPLINT_S
2293 					k->_key.key
2294 #else
2295 					NULL
2296 #endif
2297 				);
2298 #else
2299 				goto error;
2300 #endif /* GOST */
2301 				break;
2302 			case LDNS_SIGN_ECDSAP256SHA256:
2303 			case LDNS_SIGN_ECDSAP384SHA384:
2304 #ifdef USE_ECDSA
2305                                 ldns_buffer_printf(output, "Private-key-format: v1.2\n");
2306 				ldns_buffer_printf(output, "Algorithm: %d (", ldns_key_algorithm(k));
2307                                 status=ldns_algorithm2buffer_str(output, (ldns_algorithm)ldns_key_algorithm(k));
2308 #ifndef S_SPLINT_S
2309 				ldns_buffer_printf(output, ")\n");
2310                                 if(k->_key.key) {
2311                                         EC_KEY* ec = EVP_PKEY_get1_EC_KEY(k->_key.key);
2312                                         const BIGNUM* b = EC_KEY_get0_private_key(ec);
2313 					if(!ldns_print_bignum_b64_line(output, "PrivateKey", b))
2314 						goto error;
2315                                         /* down reference count in EC_KEY
2316                                          * its still assigned to the PKEY */
2317                                         EC_KEY_free(ec);
2318                                 }
2319 #endif /* splint */
2320 #else
2321 				goto error;
2322 #endif /* ECDSA */
2323                                 break;
2324 #ifdef USE_ED25519
2325 			case LDNS_SIGN_ED25519:
2326                                 ldns_buffer_printf(output, "Private-key-format: v1.2\n");
2327 				ldns_buffer_printf(output, "Algorithm: %d (", ldns_key_algorithm(k));
2328                                 status=ldns_algorithm2buffer_str(output, (ldns_algorithm)ldns_key_algorithm(k));
2329 				ldns_buffer_printf(output, ")\n");
2330 				if (status) break;
2331 				status = ldns_ed25519_key2buffer_str(output,
2332 					k->_key.key);
2333 				break;
2334 #endif /* USE_ED25519 */
2335 #ifdef USE_ED448
2336 			case LDNS_SIGN_ED448:
2337                                 ldns_buffer_printf(output, "Private-key-format: v1.2\n");
2338 				ldns_buffer_printf(output, "Algorithm: %d (", ldns_key_algorithm(k));
2339                                 status=ldns_algorithm2buffer_str(output, (ldns_algorithm)ldns_key_algorithm(k));
2340 				ldns_buffer_printf(output, ")\n");
2341 				if (status) break;
2342 				status = ldns_ed448_key2buffer_str(output,
2343 					k->_key.key);
2344 				break;
2345 #endif /* USE_ED448 */
2346 			case LDNS_SIGN_HMACMD5:
2347 				/* there's not much of a format defined for TSIG */
2348 				/* It's just a binary blob, Same for all algorithms */
2349                 ldns_buffer_printf(output, "Private-key-format: v1.2\n");
2350                 ldns_buffer_printf(output, "Algorithm: 157 (HMAC_MD5)\n");
2351 				status = ldns_hmac_key2buffer_str(output, k);
2352 				break;
2353 			case LDNS_SIGN_HMACSHA1:
2354 		        ldns_buffer_printf(output, "Private-key-format: v1.2\n");
2355 		        ldns_buffer_printf(output, "Algorithm: 158 (HMAC_SHA1)\n");
2356 				status = ldns_hmac_key2buffer_str(output, k);
2357 				break;
2358 			case LDNS_SIGN_HMACSHA224:
2359 		        ldns_buffer_printf(output, "Private-key-format: v1.2\n");
2360 		        ldns_buffer_printf(output, "Algorithm: 162 (HMAC_SHA224)\n");
2361 				status = ldns_hmac_key2buffer_str(output, k);
2362 				break;
2363 			case LDNS_SIGN_HMACSHA256:
2364 		        ldns_buffer_printf(output, "Private-key-format: v1.2\n");
2365 		        ldns_buffer_printf(output, "Algorithm: 159 (HMAC_SHA256)\n");
2366 				status = ldns_hmac_key2buffer_str(output, k);
2367 				break;
2368 			case LDNS_SIGN_HMACSHA384:
2369 		        ldns_buffer_printf(output, "Private-key-format: v1.2\n");
2370 		        ldns_buffer_printf(output, "Algorithm: 164 (HMAC_SHA384)\n");
2371 				status = ldns_hmac_key2buffer_str(output, k);
2372 				break;
2373 			case LDNS_SIGN_HMACSHA512:
2374 		        ldns_buffer_printf(output, "Private-key-format: v1.2\n");
2375 		        ldns_buffer_printf(output, "Algorithm: 165 (HMAC_SHA512)\n");
2376 				status = ldns_hmac_key2buffer_str(output, k);
2377 				break;
2378 		}
2379 #endif /* HAVE_SSL */
2380 	} else {
2381 		LDNS_FREE(bignum);
2382 		return ldns_buffer_status(output);
2383 	}
2384 	LDNS_FREE(bignum);
2385 	return status;
2386 
2387 #ifdef HAVE_SSL
2388 	/* compiles warn the label isn't used */
2389 error:
2390 	LDNS_FREE(bignum);
2391 	return LDNS_STATUS_ERR;
2392 #endif /* HAVE_SSL */
2393 
2394 }
2395 
2396 /*
2397  * Zero terminate the buffer and copy data.
2398  */
2399 char *
2400 ldns_buffer2str(ldns_buffer *buffer)
2401 {
2402 	char *str;
2403 
2404 	/* check if buffer ends with \0, if not, and
2405 	   if there is space, add it */
2406 	if (*(ldns_buffer_at(buffer, ldns_buffer_position(buffer))) != 0) {
2407 		if (!ldns_buffer_reserve(buffer, 1)) {
2408 			return NULL;
2409 		}
2410 		ldns_buffer_write_u8(buffer, (uint8_t) '\0');
2411 		if (!ldns_buffer_set_capacity(buffer, ldns_buffer_position(buffer))) {
2412 			return NULL;
2413 		}
2414 	}
2415 
2416 	str = strdup((const char *)ldns_buffer_begin(buffer));
2417         if(!str) {
2418                 return NULL;
2419         }
2420 	return str;
2421 }
2422 
2423 /*
2424  * Zero terminate the buffer and export data.
2425  */
2426 char *
2427 ldns_buffer_export2str(ldns_buffer *buffer)
2428 {
2429 	/* Append '\0' as string terminator */
2430 	if (! ldns_buffer_reserve(buffer, 1)) {
2431 		return NULL;
2432 	}
2433 	ldns_buffer_write_u8(buffer, 0);
2434 
2435 	/* reallocate memory to the size of the string and export */
2436 	ldns_buffer_set_capacity(buffer, ldns_buffer_position(buffer));
2437 	return ldns_buffer_export(buffer);
2438 }
2439 
2440 char *
2441 ldns_rdf2str(const ldns_rdf *rdf)
2442 {
2443 	char *result = NULL;
2444 	ldns_buffer *tmp_buffer = ldns_buffer_new(LDNS_MAX_PACKETLEN);
2445 
2446 	if (!tmp_buffer) {
2447 		return NULL;
2448 	}
2449 	if (ldns_rdf2buffer_str(tmp_buffer, rdf) == LDNS_STATUS_OK) {
2450 		/* export and return string, destroy rest */
2451 		result = ldns_buffer_export2str(tmp_buffer);
2452 	}
2453 	ldns_buffer_free(tmp_buffer);
2454 	return result;
2455 }
2456 
2457 char *
2458 ldns_rr2str_fmt(const ldns_output_format *fmt, const ldns_rr *rr)
2459 {
2460 	char *result = NULL;
2461 	ldns_buffer *tmp_buffer = ldns_buffer_new(LDNS_MAX_PACKETLEN);
2462 
2463 	if (!tmp_buffer) {
2464 		return NULL;
2465 	}
2466 	if (ldns_rr2buffer_str_fmt(tmp_buffer, fmt, rr)
2467 		       	== LDNS_STATUS_OK) {
2468 		/* export and return string, destroy rest */
2469 		result = ldns_buffer_export2str(tmp_buffer);
2470 	}
2471 	ldns_buffer_free(tmp_buffer);
2472 	return result;
2473 }
2474 
2475 char *
2476 ldns_rr2str(const ldns_rr *rr)
2477 {
2478 	return ldns_rr2str_fmt(ldns_output_format_default, rr);
2479 }
2480 
2481 char *
2482 ldns_pkt2str_fmt(const ldns_output_format *fmt, const ldns_pkt *pkt)
2483 {
2484 	char *result = NULL;
2485 	ldns_buffer *tmp_buffer = ldns_buffer_new(LDNS_MAX_PACKETLEN);
2486 
2487 	if (!tmp_buffer) {
2488 		return NULL;
2489 	}
2490 	if (ldns_pkt2buffer_str_fmt(tmp_buffer, fmt, pkt)
2491 		       	== LDNS_STATUS_OK) {
2492 		/* export and return string, destroy rest */
2493 		result = ldns_buffer_export2str(tmp_buffer);
2494 	}
2495 
2496 	ldns_buffer_free(tmp_buffer);
2497 	return result;
2498 }
2499 
2500 char *
2501 ldns_pkt2str(const ldns_pkt *pkt)
2502 {
2503 	return ldns_pkt2str_fmt(ldns_output_format_default, pkt);
2504 }
2505 
2506 char *
2507 ldns_key2str(const ldns_key *k)
2508 {
2509 	char *result = NULL;
2510 	ldns_buffer *tmp_buffer = ldns_buffer_new(LDNS_MAX_PACKETLEN);
2511 
2512 	if (!tmp_buffer) {
2513 		return NULL;
2514 	}
2515 	if (ldns_key2buffer_str(tmp_buffer, k) == LDNS_STATUS_OK) {
2516 		/* export and return string, destroy rest */
2517 		result = ldns_buffer_export2str(tmp_buffer);
2518 	}
2519 	ldns_buffer_free(tmp_buffer);
2520 	return result;
2521 }
2522 
2523 char *
2524 ldns_rr_list2str_fmt(const ldns_output_format *fmt, const ldns_rr_list *list)
2525 {
2526 	char *result = NULL;
2527 	ldns_buffer *tmp_buffer = ldns_buffer_new(LDNS_MAX_PACKETLEN);
2528 
2529 	if (!tmp_buffer) {
2530 		return NULL;
2531 	}
2532 	if (list) {
2533 		if (ldns_rr_list2buffer_str_fmt(
2534 				   tmp_buffer, fmt, list)
2535 			       	== LDNS_STATUS_OK) {
2536 		}
2537 	} else {
2538 		if (fmt == NULL) {
2539 			fmt = ldns_output_format_default;
2540 		}
2541 		if (fmt->flags & LDNS_COMMENT_NULLS) {
2542 			ldns_buffer_printf(tmp_buffer, "; (null)\n");
2543 		}
2544 	}
2545 
2546 	/* export and return string, destroy rest */
2547 	result = ldns_buffer_export2str(tmp_buffer);
2548 	ldns_buffer_free(tmp_buffer);
2549 	return result;
2550 }
2551 
2552 char *
2553 ldns_rr_list2str(const ldns_rr_list *list)
2554 {
2555 	return ldns_rr_list2str_fmt(ldns_output_format_default, list);
2556 }
2557 
2558 void
2559 ldns_rdf_print(FILE *output, const ldns_rdf *rdf)
2560 {
2561 	char *str = ldns_rdf2str(rdf);
2562 	if (str) {
2563 		fprintf(output, "%s", str);
2564 	} else {
2565 		fprintf(output, ";Unable to convert rdf to string\n");
2566 	}
2567 	LDNS_FREE(str);
2568 }
2569 
2570 void
2571 ldns_rr_print_fmt(FILE *output,
2572 		const ldns_output_format *fmt, const ldns_rr *rr)
2573 {
2574 	char *str = ldns_rr2str_fmt(fmt, rr);
2575 	if (str) {
2576 		fprintf(output, "%s", str);
2577 	} else {
2578 		fprintf(output, ";Unable to convert rr to string\n");
2579 	}
2580 	LDNS_FREE(str);
2581 }
2582 
2583 void
2584 ldns_rr_print(FILE *output, const ldns_rr *rr)
2585 {
2586 	ldns_rr_print_fmt(output, ldns_output_format_default, rr);
2587 }
2588 
2589 void
2590 ldns_pkt_print_fmt(FILE *output,
2591 		const ldns_output_format *fmt, const ldns_pkt *pkt)
2592 {
2593 	char *str = ldns_pkt2str_fmt(fmt, pkt);
2594 	if (str) {
2595 		fprintf(output, "%s", str);
2596 	} else {
2597 		fprintf(output, ";Unable to convert packet to string\n");
2598 	}
2599 	LDNS_FREE(str);
2600 }
2601 
2602 void
2603 ldns_pkt_print(FILE *output, const ldns_pkt *pkt)
2604 {
2605 	ldns_pkt_print_fmt(output, ldns_output_format_default, pkt);
2606 }
2607 
2608 void
2609 ldns_rr_list_print_fmt(FILE *output,
2610 		const ldns_output_format *fmt, const ldns_rr_list *lst)
2611 {
2612 	size_t i;
2613 	for (i = 0; i < ldns_rr_list_rr_count(lst); i++) {
2614 		ldns_rr_print_fmt(output, fmt, ldns_rr_list_rr(lst, i));
2615 	}
2616 }
2617 
2618 void
2619 ldns_rr_list_print(FILE *output, const ldns_rr_list *lst)
2620 {
2621 	ldns_rr_list_print_fmt(output, ldns_output_format_default, lst);
2622 }
2623 
2624 void
2625 ldns_resolver_print_fmt(FILE *output,
2626 		const ldns_output_format *fmt, const ldns_resolver *r)
2627 {
2628 	uint16_t i;
2629 	ldns_rdf **n;
2630 	ldns_rdf **s;
2631 	size_t *rtt;
2632 	if (!r) {
2633 		return;
2634 	}
2635 	n = ldns_resolver_nameservers(r);
2636 	s = ldns_resolver_searchlist(r);
2637 	rtt = ldns_resolver_rtt(r);
2638 
2639 	fprintf(output, "port: %d\n", (int)ldns_resolver_port(r));
2640 	fprintf(output, "edns0 size: %d\n", (int)ldns_resolver_edns_udp_size(r));
2641 	fprintf(output, "use ip6: %d\n", (int)ldns_resolver_ip6(r));
2642 
2643 	fprintf(output, "recursive: %d\n", ldns_resolver_recursive(r));
2644 	fprintf(output, "usevc: %d\n", ldns_resolver_usevc(r));
2645 	fprintf(output, "igntc: %d\n", ldns_resolver_igntc(r));
2646 	fprintf(output, "fail: %d\n", ldns_resolver_fail(r));
2647 	fprintf(output, "retry: %d\n", (int)ldns_resolver_retry(r));
2648 	fprintf(output, "retrans: %d\n", (int)ldns_resolver_retrans(r));
2649 	fprintf(output, "fallback: %d\n", ldns_resolver_fallback(r));
2650 	fprintf(output, "random: %d\n", ldns_resolver_random(r));
2651 	fprintf(output, "timeout: %d\n", (int)ldns_resolver_timeout(r).tv_sec);
2652 	fprintf(output, "dnssec: %d\n", ldns_resolver_dnssec(r));
2653 	fprintf(output, "dnssec cd: %d\n", ldns_resolver_dnssec_cd(r));
2654 	fprintf(output, "trust anchors (%d listed):\n",
2655 		(int)ldns_rr_list_rr_count(ldns_resolver_dnssec_anchors(r)));
2656 	ldns_rr_list_print_fmt(output, fmt, ldns_resolver_dnssec_anchors(r));
2657 	fprintf(output, "tsig: %s %s\n",
2658                 ldns_resolver_tsig_keyname(r)?ldns_resolver_tsig_keyname(r):"-",
2659                 ldns_resolver_tsig_algorithm(r)?ldns_resolver_tsig_algorithm(r):"-");
2660 	fprintf(output, "debug: %d\n", ldns_resolver_debug(r));
2661 
2662 	fprintf(output, "default domain: ");
2663 	ldns_rdf_print(output, ldns_resolver_domain(r));
2664 	fprintf(output, "\n");
2665 	fprintf(output, "apply default domain: %d\n", ldns_resolver_defnames(r));
2666 
2667 	fprintf(output, "searchlist (%d listed):\n",  (int)ldns_resolver_searchlist_count(r));
2668 	for (i = 0; i < ldns_resolver_searchlist_count(r); i++) {
2669 		fprintf(output, "\t");
2670 		ldns_rdf_print(output, s[i]);
2671 		fprintf(output, "\n");
2672 	}
2673 	fprintf(output, "apply search list: %d\n", ldns_resolver_dnsrch(r));
2674 
2675 	fprintf(output, "nameservers (%d listed):\n", (int)ldns_resolver_nameserver_count(r));
2676 	for (i = 0; i < ldns_resolver_nameserver_count(r); i++) {
2677 		fprintf(output, "\t");
2678 		ldns_rdf_print(output, n[i]);
2679 
2680 		switch ((int)rtt[i]) {
2681 			case LDNS_RESOLV_RTT_MIN:
2682 			fprintf(output, " - reachable\n");
2683 			break;
2684 			case LDNS_RESOLV_RTT_INF:
2685 			fprintf(output, " - unreachable\n");
2686 			break;
2687 		}
2688 	}
2689 }
2690 
2691 void
2692 ldns_resolver_print(FILE *output, const ldns_resolver *r)
2693 {
2694 	ldns_resolver_print_fmt(output, ldns_output_format_default, r);
2695 }
2696 
2697 void
2698 ldns_zone_print_fmt(FILE *output,
2699 		const ldns_output_format *fmt, const ldns_zone *z)
2700 {
2701 	if(ldns_zone_soa(z))
2702 		ldns_rr_print_fmt(output, fmt, ldns_zone_soa(z));
2703 	ldns_rr_list_print_fmt(output, fmt, ldns_zone_rrs(z));
2704 }
2705 void
2706 ldns_zone_print(FILE *output, const ldns_zone *z)
2707 {
2708 	ldns_zone_print_fmt(output, ldns_output_format_default, z);
2709 }
2710