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