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