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