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