host2str.c revision 246854
197403Sobrien/*
297403Sobrien * host2str.c
3169691Skan *
4169691Skan * conversion routines from the host format
597403Sobrien * to the presentation format (strings)
697403Sobrien *
797403Sobrien * a Net::DNS like library for C
897403Sobrien *
997403Sobrien * (c) NLnet Labs, 2004-2006
1097403Sobrien *
1197403Sobrien * See the file LICENSE for the license
1297403Sobrien */
1397403Sobrien#include <ldns/config.h>
1497403Sobrien
1597403Sobrien#include <ldns/ldns.h>
1697403Sobrien
1797403Sobrien#include <limits.h>
1897403Sobrien
19169691Skan#ifdef HAVE_SYS_SOCKET_H
2097403Sobrien#include <sys/socket.h>
2197403Sobrien#endif
2297403Sobrien#ifdef HAVE_ARPA_INET_H
2397403Sobrien#include <arpa/inet.h>
2497403Sobrien#endif
2597403Sobrien#ifdef HAVE_NETDB_H
2697403Sobrien#include <netdb.h>
2797403Sobrien#endif
2897403Sobrien#include <time.h>
2997403Sobrien#include <sys/time.h>
3097403Sobrien
3197403Sobrien#ifndef INET_ADDRSTRLEN
3297403Sobrien#define INET_ADDRSTRLEN 16
3397403Sobrien#endif
3497403Sobrien#ifndef INET6_ADDRSTRLEN
3597403Sobrien#define INET6_ADDRSTRLEN 46
3697403Sobrien#endif
3797403Sobrien
3897403Sobrien/* lookup tables for standard DNS stuff  */
3997403Sobrien
4097403Sobrien/* Taken from RFC 2535, section 7.  */
4197403Sobrienldns_lookup_table ldns_algorithms[] = {
4297403Sobrien        { LDNS_RSAMD5, "RSAMD5" },
4397403Sobrien        { LDNS_DH, "DH" },
4497403Sobrien        { LDNS_DSA, "DSA" },
4597403Sobrien        { LDNS_ECC, "ECC" },
4697403Sobrien        { LDNS_RSASHA1, "RSASHA1" },
4797403Sobrien        { LDNS_DSA_NSEC3, "DSA-NSEC3-SHA1" },
4897403Sobrien        { LDNS_RSASHA1_NSEC3, "RSASHA1-NSEC3-SHA1" },
4997403Sobrien#ifdef USE_SHA2
5097403Sobrien	{ LDNS_RSASHA256, "RSASHA256"},
5197403Sobrien	{ LDNS_RSASHA512, "RSASHA512"},
5297403Sobrien#endif
5397403Sobrien#ifdef USE_GOST
5497403Sobrien	{ LDNS_ECC_GOST, "ECC-GOST"},
5597403Sobrien#endif
5697403Sobrien#ifdef USE_ECDSA
5797403Sobrien        { LDNS_ECDSAP256SHA256, "ECDSAP256SHA256"},
5897403Sobrien        { LDNS_ECDSAP384SHA384, "ECDSAP384SHA384"},
5997403Sobrien#endif
6097403Sobrien        { LDNS_INDIRECT, "INDIRECT" },
6197403Sobrien        { LDNS_PRIVATEDNS, "PRIVATEDNS" },
62132720Skan        { LDNS_PRIVATEOID, "PRIVATEOID" },
63132720Skan        { 0, NULL }
6497403Sobrien};
6597403Sobrien
6697403Sobrien/* Taken from RFC 4398  */
6797403Sobrienldns_lookup_table ldns_cert_algorithms[] = {
6897403Sobrien        { LDNS_CERT_PKIX, "PKIX" },
6997403Sobrien        { LDNS_CERT_SPKI, "SPKI" },
7097403Sobrien        { LDNS_CERT_PGP, "PGP" },
7197403Sobrien        { LDNS_CERT_IPKIX, "IPKIX" },
72169691Skan        { LDNS_CERT_ISPKI, "ISPKI" },
73169691Skan        { LDNS_CERT_IPGP, "IPGP" },
7497403Sobrien        { LDNS_CERT_ACPKIX, "ACPKIX" },
7597403Sobrien        { LDNS_CERT_IACPKIX, "IACPKIX" },
7697403Sobrien        { LDNS_CERT_URI, "URI" },
7797403Sobrien        { LDNS_CERT_OID, "OID" },
78132720Skan        { 0, NULL }
7997403Sobrien};
80169691Skan
81169691Skan/* classes  */
8297403Sobrienldns_lookup_table ldns_rr_classes[] = {
83169691Skan        { LDNS_RR_CLASS_IN, "IN" },
84169691Skan        { LDNS_RR_CLASS_CH, "CH" },
85169691Skan        { LDNS_RR_CLASS_HS, "HS" },
86169691Skan        { LDNS_RR_CLASS_NONE, "NONE" },
87169691Skan        { LDNS_RR_CLASS_ANY, "ANY" },
88169691Skan        { 0, NULL }
89169691Skan};
90169691Skan
91169691Skan/* if these are used elsewhere */
92169691Skanldns_lookup_table ldns_rcodes[] = {
93169691Skan        { LDNS_RCODE_NOERROR, "NOERROR" },
94169691Skan        { LDNS_RCODE_FORMERR, "FORMERR" },
95169691Skan        { LDNS_RCODE_SERVFAIL, "SERVFAIL" },
96169691Skan        { LDNS_RCODE_NXDOMAIN, "NXDOMAIN" },
97169691Skan        { LDNS_RCODE_NOTIMPL, "NOTIMPL" },
98169691Skan        { LDNS_RCODE_REFUSED, "REFUSED" },
99169691Skan        { LDNS_RCODE_YXDOMAIN, "YXDOMAIN" },
100169691Skan        { LDNS_RCODE_YXRRSET, "YXRRSET" },
101169691Skan        { LDNS_RCODE_NXRRSET, "NXRRSET" },
102169691Skan        { LDNS_RCODE_NOTAUTH, "NOTAUTH" },
103169691Skan        { LDNS_RCODE_NOTZONE, "NOTZONE" },
104169691Skan        { 0, NULL }
105169691Skan};
106169691Skan
107169691Skanldns_lookup_table ldns_opcodes[] = {
108169691Skan        { LDNS_PACKET_QUERY, "QUERY" },
109169691Skan        { LDNS_PACKET_IQUERY, "IQUERY" },
110169691Skan        { LDNS_PACKET_STATUS, "STATUS" },
111169691Skan	{ LDNS_PACKET_NOTIFY, "NOTIFY" },
112169691Skan	{ LDNS_PACKET_UPDATE, "UPDATE" },
113169691Skan        { 0, NULL }
114169691Skan};
115169691Skan
116169691Skanconst ldns_output_format   ldns_output_format_nocomments_record = { 0, NULL };
117169691Skanconst ldns_output_format  *ldns_output_format_nocomments
118169691Skan			= &ldns_output_format_nocomments_record;
119169691Skanconst ldns_output_format   ldns_output_format_onlykeyids_record = {
120169691Skan	LDNS_COMMENT_KEY, NULL
121169691Skan};
122169691Skanconst ldns_output_format  *ldns_output_format_onlykeyids
123169691Skan			= &ldns_output_format_onlykeyids_record;
124169691Skanconst ldns_output_format  *ldns_output_format_default
125169691Skan			= &ldns_output_format_onlykeyids_record;
126169691Skan
127169691Skanconst ldns_output_format   ldns_output_format_bubblebabble_record = {
128169691Skan	LDNS_COMMENT_KEY | LDNS_COMMENT_BUBBLEBABBLE | LDNS_COMMENT_FLAGS, NULL
129169691Skan};
130169691Skanconst ldns_output_format  *ldns_output_format_bubblebabble
131169691Skan			= &ldns_output_format_bubblebabble_record;
132169691Skan
13397403Sobrienldns_status
13497403Sobrienldns_pkt_opcode2buffer_str(ldns_buffer *output, ldns_pkt_opcode opcode)
13597403Sobrien{
13697403Sobrien	ldns_lookup_table *lt = ldns_lookup_by_id(ldns_opcodes, opcode);
13797403Sobrien	if (lt && lt->name) {
13897403Sobrien		ldns_buffer_printf(output, "%s", lt->name);
13997403Sobrien	} else {
14097403Sobrien		ldns_buffer_printf(output, "OPCODE%u", opcode);
141132720Skan	}
14297403Sobrien	return ldns_buffer_status(output);
143132720Skan}
14497403Sobrien
145132720Skanldns_status
146132720Skanldns_pkt_rcode2buffer_str(ldns_buffer *output, ldns_pkt_rcode rcode)
147132720Skan{
148132720Skan	ldns_lookup_table *lt = ldns_lookup_by_id(ldns_rcodes, rcode);
14997403Sobrien	if (lt && lt->name) {
15097403Sobrien		ldns_buffer_printf(output, "%s", lt->name);
151132720Skan	} else {
152132720Skan		ldns_buffer_printf(output, "RCODE%u", rcode);
153132720Skan	}
154132720Skan	return ldns_buffer_status(output);
155132720Skan}
156132720Skan
157132720Skanldns_status
158132720Skanldns_algorithm2buffer_str(ldns_buffer *output,
15997403Sobrien                          ldns_algorithm algorithm)
160169691Skan{
161169691Skan	ldns_lookup_table *lt = ldns_lookup_by_id(ldns_algorithms,
162169691Skan	                                          algorithm);
163169691Skan	if (lt && lt->name) {
164169691Skan		ldns_buffer_printf(output, "%s", lt->name);
165169691Skan	} else {
166169691Skan		ldns_buffer_printf(output, "ALG%u", algorithm);
167169691Skan	}
16897403Sobrien	return ldns_buffer_status(output);
16997403Sobrien}
17097403Sobrien
17197403Sobrienldns_status
17297403Sobrienldns_cert_algorithm2buffer_str(ldns_buffer *output,
17397403Sobrien                               ldns_cert_algorithm cert_algorithm)
17497403Sobrien{
17597403Sobrien	ldns_lookup_table *lt = ldns_lookup_by_id(ldns_cert_algorithms,
17697403Sobrien	                                          cert_algorithm);
17797403Sobrien	if (lt && lt->name) {
17897403Sobrien		ldns_buffer_printf(output, "%s", lt->name);
17997403Sobrien	} else {
18097403Sobrien		ldns_buffer_printf(output, "CERT_ALG%u",
18197403Sobrien		                   cert_algorithm);
18297403Sobrien	}
18397403Sobrien	return ldns_buffer_status(output);
18497403Sobrien}
185132720Skan
18697403Sobrienchar *
187132720Skanldns_pkt_opcode2str(ldns_pkt_opcode opcode)
188132720Skan{
189132720Skan	char *str;
19097403Sobrien	ldns_buffer *buf;
19197403Sobrien
19297403Sobrien	buf = ldns_buffer_new(12);
19397403Sobrien	if (!buf) {
19497403Sobrien		return NULL;
19597403Sobrien	}
19697403Sobrien
19797403Sobrien	str = NULL;
19897403Sobrien	if (ldns_pkt_opcode2buffer_str(buf, opcode) == LDNS_STATUS_OK) {
19997403Sobrien		str = ldns_buffer_export2str(buf);
20097403Sobrien	}
20197403Sobrien
20297403Sobrien	ldns_buffer_free(buf);
20397403Sobrien	return str;
204132720Skan}
20597403Sobrien
20697403Sobrienchar *
207132720Skanldns_pkt_rcode2str(ldns_pkt_rcode rcode)
20897403Sobrien{
209132720Skan	char *str;
210132720Skan	ldns_buffer *buf;
211132720Skan
21297403Sobrien	buf = ldns_buffer_new(10);
21397403Sobrien	if (!buf) {
21497403Sobrien		return NULL;
21597403Sobrien	}
21697403Sobrien
21797403Sobrien	str = NULL;
21897403Sobrien	if (ldns_pkt_rcode2buffer_str(buf, rcode) == LDNS_STATUS_OK) {
21997403Sobrien		str = ldns_buffer_export2str(buf);
22097403Sobrien	}
22197403Sobrien
22297403Sobrien	ldns_buffer_free(buf);
22397403Sobrien	return str;
22497403Sobrien}
22597403Sobrien
22697403Sobrienchar *
22797403Sobrienldns_pkt_algorithm2str(ldns_algorithm algorithm)
22897403Sobrien{
229132720Skan	char *str;
230132720Skan	ldns_buffer *buf;
231132720Skan
23297403Sobrien	buf = ldns_buffer_new(10);
23397403Sobrien	if (!buf) {
23497403Sobrien		return NULL;
23597403Sobrien	}
23697403Sobrien
23797403Sobrien	str = NULL;
23897403Sobrien	if (ldns_algorithm2buffer_str(buf, algorithm)
23997403Sobrien	    == LDNS_STATUS_OK) {
24097403Sobrien		str = ldns_buffer_export2str(buf);
24197403Sobrien	}
24297403Sobrien
24397403Sobrien	ldns_buffer_free(buf);
24497403Sobrien	return str;
24597403Sobrien}
24697403Sobrien
24797403Sobrienchar *
24897403Sobrienldns_pkt_cert_algorithm2str(ldns_cert_algorithm cert_algorithm)
249132720Skan{
250132720Skan	char *str;
251132720Skan	ldns_buffer *buf;
25297403Sobrien
25397403Sobrien	buf = ldns_buffer_new(10);
254169691Skan	if (!buf) {
25597403Sobrien		return NULL;
25697403Sobrien	}
25797403Sobrien
25897403Sobrien	str = NULL;
25997403Sobrien	if (ldns_cert_algorithm2buffer_str(buf, cert_algorithm)
260169691Skan	    == LDNS_STATUS_OK) {
261169691Skan		str = ldns_buffer_export2str(buf);
26297403Sobrien	}
263169691Skan
264169691Skan	ldns_buffer_free(buf);
265169691Skan	return str;
266169691Skan}
267169691Skan
268169691Skan
269169691Skan/* do NOT pass compressed data here :p */
270169691Skanldns_status
271169691Skanldns_rdf2buffer_str_dname(ldns_buffer *output, const ldns_rdf *dname)
27297403Sobrien{
273169691Skan	/* can we do with 1 pos var? or without at all? */
274169691Skan	uint8_t src_pos = 0;
27597403Sobrien	uint8_t len;
276169691Skan	uint8_t *data;
277169691Skan	uint8_t i;
278169691Skan	unsigned char c;
279169691Skan
280169691Skan	data = (uint8_t*)ldns_rdf_data(dname);
281169691Skan	len = data[src_pos];
282169691Skan
283169691Skan	if (ldns_rdf_size(dname) > LDNS_MAX_DOMAINLEN) {
284169691Skan		/* too large, return */
285169691Skan		return LDNS_STATUS_DOMAINNAME_OVERFLOW;
286169691Skan	}
287169691Skan
288132720Skan	/* special case: root label */
289169691Skan	if (1 == ldns_rdf_size(dname)) {
29097403Sobrien		ldns_buffer_printf(output, ".");
291169691Skan	} else {
292169691Skan		while ((len > 0) && src_pos < ldns_rdf_size(dname)) {
29397403Sobrien			src_pos++;
294169691Skan			for(i = 0; i < len; i++) {
295169691Skan				/* paranoia check for various 'strange'
296169691Skan				   characters in dnames
297169691Skan				*/
298169691Skan				c = (unsigned char) data[src_pos];
299169691Skan				if(c == '.' || c == ';' ||
300169691Skan				   c == '(' || c == ')' ||
301169691Skan				   c == '\\') {
302169691Skan					ldns_buffer_printf(output, "\\%c",
303169691Skan							data[src_pos]);
304169691Skan				} else if (!(isascii(c) && isgraph(c))) {
305169691Skan					ldns_buffer_printf(output, "\\%03u",
306169691Skan						        data[src_pos]);
307169691Skan				} else {
308169691Skan					ldns_buffer_printf(output, "%c", data[src_pos]);
309169691Skan				}
310169691Skan				src_pos++;
311169691Skan			}
312169691Skan
313169691Skan			if (src_pos < ldns_rdf_size(dname)) {
314169691Skan				ldns_buffer_printf(output, ".");
315169691Skan			}
31697403Sobrien			len = data[src_pos];
31797403Sobrien		}
318169691Skan	}
319169691Skan	return ldns_buffer_status(output);
320169691Skan}
321169691Skan
322169691Skanldns_status
32397403Sobrienldns_rdf2buffer_str_int8(ldns_buffer *output, const ldns_rdf *rdf)
324169691Skan{
325169691Skan	uint8_t data = ldns_rdf_data(rdf)[0];
326169691Skan	ldns_buffer_printf(output, "%lu", (unsigned long) data);
327169691Skan	return ldns_buffer_status(output);
32897403Sobrien}
329169691Skan
330169691Skanldns_status
331169691Skanldns_rdf2buffer_str_int16(ldns_buffer *output, const ldns_rdf *rdf)
332169691Skan{
33397403Sobrien	uint16_t data = ldns_read_uint16(ldns_rdf_data(rdf));
334169691Skan	ldns_buffer_printf(output, "%lu", (unsigned long) data);
335169691Skan	return ldns_buffer_status(output);
33697403Sobrien}
337169691Skan
338169691Skanldns_status
339169691Skanldns_rdf2buffer_str_int32(ldns_buffer *output, const ldns_rdf *rdf)
340169691Skan{
341169691Skan	uint32_t data = ldns_read_uint32(ldns_rdf_data(rdf));
34297403Sobrien	ldns_buffer_printf(output, "%lu", (unsigned long) data);
343169691Skan	return ldns_buffer_status(output);
344169691Skan}
34597403Sobrien
346169691Skanldns_status
347169691Skanldns_rdf2buffer_str_time(ldns_buffer *output, const ldns_rdf *rdf)
348169691Skan{
349169691Skan	/* create a YYYYMMDDHHMMSS string if possible */
350169691Skan	struct tm tm;
35197403Sobrien	char date_buf[16];
352169691Skan
353169691Skan	memset(&tm, 0, sizeof(tm));
35497403Sobrien	if (ldns_serial_arithmitics_gmtime_r(ldns_rdf2native_int32(rdf), time(NULL), &tm)
355169691Skan	    && strftime(date_buf, 15, "%Y%m%d%H%M%S", &tm)) {
356169691Skan		ldns_buffer_printf(output, "%s", date_buf);
357169691Skan	}
358169691Skan	return ldns_buffer_status(output);
359169691Skan}
36097403Sobrien
361169691Skanldns_status
362169691Skanldns_rdf2buffer_str_a(ldns_buffer *output, const ldns_rdf *rdf)
36397403Sobrien{
364169691Skan	char str[INET_ADDRSTRLEN];
365169691Skan
366169691Skan	if (inet_ntop(AF_INET, ldns_rdf_data(rdf), str, INET_ADDRSTRLEN)) {
367169691Skan		ldns_buffer_printf(output, "%s", str);
368169691Skan	}
369169691Skan	return ldns_buffer_status(output);
37097403Sobrien}
37197403Sobrien
37297403Sobrienldns_status
37397403Sobrienldns_rdf2buffer_str_aaaa(ldns_buffer *output, const ldns_rdf *rdf)
37497403Sobrien{
37597403Sobrien	char str[INET6_ADDRSTRLEN];
376258429Spfg
37797403Sobrien	if (inet_ntop(AF_INET6, ldns_rdf_data(rdf), str, INET6_ADDRSTRLEN)) {
37897403Sobrien		ldns_buffer_printf(output, "%s", str);
37997403Sobrien	}
38097403Sobrien
381132720Skan	return ldns_buffer_status(output);
382132720Skan}
383132720Skan
384132720Skanldns_status
385132720Skanldns_rdf2buffer_str_str(ldns_buffer *output, const ldns_rdf *rdf)
38697403Sobrien{
387132720Skan	const uint8_t *data = ldns_rdf_data(rdf);
388132720Skan	uint8_t length = data[0];
389132720Skan	size_t i;
390132720Skan
39197403Sobrien	ldns_buffer_printf(output, "\"");
39297403Sobrien	for (i = 1; i <= length; ++i) {
393132720Skan		char ch = (char) data[i];
394132720Skan		if (isprint((int)ch) || ch=='\t') {
395132720Skan			if (ch=='\"'||ch=='\\')
396132720Skan				ldns_buffer_printf(output, "\\%c", ch);
39797403Sobrien			else
398169691Skan				ldns_buffer_printf(output, "%c", ch);
399169691Skan		} else {
400169691Skan			ldns_buffer_printf(output, "\\%03u",
401169691Skan                                (unsigned)(uint8_t) ch);
40297403Sobrien		}
40397403Sobrien	}
404169691Skan	ldns_buffer_printf(output, "\"");
405169691Skan	return ldns_buffer_status(output);
406169691Skan}
407169691Skan
408169691Skanldns_status
409169691Skanldns_rdf2buffer_str_b64(ldns_buffer *output, const ldns_rdf *rdf)
41097403Sobrien{
411169691Skan	size_t size = ldns_b64_ntop_calculate_size(ldns_rdf_size(rdf));
412169691Skan	char *b64 = LDNS_XMALLOC(char, size);
41397403Sobrien	if(!b64) return LDNS_STATUS_MEM_ERR;
414169691Skan	if (ldns_b64_ntop(ldns_rdf_data(rdf), ldns_rdf_size(rdf), b64, size)) {
415169691Skan		ldns_buffer_printf(output, "%s", b64);
416169691Skan	}
417169691Skan	LDNS_FREE(b64);
418169691Skan	return ldns_buffer_status(output);
419169691Skan}
420169691Skan
421169691Skanldns_status
42297403Sobrienldns_rdf2buffer_str_b32_ext(ldns_buffer *output, const ldns_rdf *rdf)
42397403Sobrien{
424169691Skan	size_t size;
425169691Skan	char *b32;
42697403Sobrien	if(ldns_rdf_size(rdf) == 0)
427169691Skan		return LDNS_STATUS_OK;
428169691Skan        /* remove -1 for the b32-hash-len octet */
429169691Skan	size = ldns_b32_ntop_calculate_size(ldns_rdf_size(rdf) - 1);
430169691Skan        /* add one for the end nul for the string */
431169691Skan	b32 = LDNS_XMALLOC(char, size + 1);
432169691Skan	if(!b32) return LDNS_STATUS_MEM_ERR;
433169691Skan	size = (size_t) ldns_b32_ntop_extended_hex(ldns_rdf_data(rdf) + 1,
434169691Skan		ldns_rdf_size(rdf) - 1, b32, size+1);
435169691Skan	if (size > 0) {
43697403Sobrien		ldns_buffer_printf(output, "%s", b32);
43797403Sobrien	}
438169691Skan	LDNS_FREE(b32);
439169691Skan	return ldns_buffer_status(output);
44097403Sobrien}
441169691Skan
442169691Skanldns_status
443169691Skanldns_rdf2buffer_str_hex(ldns_buffer *output, const ldns_rdf *rdf)
444169691Skan{
445169691Skan	size_t i;
446169691Skan	for (i = 0; i < ldns_rdf_size(rdf); i++) {
447169691Skan		ldns_buffer_printf(output, "%02x", ldns_rdf_data(rdf)[i]);
448169691Skan	}
44997403Sobrien
45097403Sobrien	return ldns_buffer_status(output);
45197403Sobrien}
45297403Sobrien
45397403Sobrienldns_status
45497403Sobrienldns_rdf2buffer_str_type(ldns_buffer *output, const ldns_rdf *rdf)
455169691Skan{
456169691Skan        uint16_t data = ldns_read_uint16(ldns_rdf_data(rdf));
457169691Skan	const ldns_rr_descriptor *descriptor;
458169691Skan
459169691Skan	descriptor = ldns_rr_descript(data);
460169691Skan	if (descriptor && descriptor->_name) {
461169691Skan		ldns_buffer_printf(output, "%s", descriptor->_name);
462169691Skan	} else {
463169691Skan		ldns_buffer_printf(output, "TYPE%u", data);
464169691Skan	}
465169691Skan	return ldns_buffer_status(output);
46697403Sobrien}
46797403Sobrien
468169691Skanldns_status
469169691Skanldns_rdf2buffer_str_class(ldns_buffer *output, const ldns_rdf *rdf)
470169691Skan{
471169691Skan	uint16_t data = ldns_read_uint16(ldns_rdf_data(rdf));
472169691Skan	ldns_lookup_table *lt;
473169691Skan
474169691Skan 	lt = ldns_lookup_by_id(ldns_rr_classes, (int) data);
475169691Skan	if (lt) {
47697403Sobrien		ldns_buffer_printf(output, "\t%s", lt->name);
477169691Skan	} else {
478169691Skan		ldns_buffer_printf(output, "\tCLASS%d", data);
479169691Skan	}
480169691Skan	return ldns_buffer_status(output);
481169691Skan}
482169691Skan
483169691Skanldns_status
484169691Skanldns_rdf2buffer_str_cert_alg(ldns_buffer *output, const ldns_rdf *rdf)
485169691Skan{
48697403Sobrien        uint16_t data = ldns_read_uint16(ldns_rdf_data(rdf));
487169691Skan	ldns_lookup_table *lt;
488169691Skan 	lt = ldns_lookup_by_id(ldns_cert_algorithms, (int) data);
48997403Sobrien	if (lt) {
490169691Skan		ldns_buffer_printf(output, "%s", lt->name);
491169691Skan	} else {
492169691Skan		ldns_buffer_printf(output, "%d", data);
493169691Skan	}
494169691Skan	return ldns_buffer_status(output);
495169691Skan}
49697403Sobrien
497169691Skanldns_status
498169691Skanldns_rdf2buffer_str_alg(ldns_buffer *output, const ldns_rdf *rdf)
49997403Sobrien{
500169691Skan	/* don't use algorithm mnemonics in the presentation format
501169691Skan	   this kind of got sneaked into the rfc's */
502169691Skan        uint8_t data = ldns_rdf_data(rdf)[0];
503169691Skan		ldns_buffer_printf(output, "%d", data);
504169691Skan	return ldns_buffer_status(output);
505169691Skan}
50697403Sobrien
50797403Sobrienstatic void
50897403Sobrienloc_cm_print(ldns_buffer *output, uint8_t mantissa, uint8_t exponent)
509132720Skan{
510132720Skan	uint8_t i;
511132720Skan	/* is it 0.<two digits> ? */
51297403Sobrien	if(exponent < 2) {
51397403Sobrien		if(exponent == 1)
51497403Sobrien			mantissa *= 10;
51597403Sobrien		ldns_buffer_printf(output, "0.%02ld", (long)mantissa);
51697403Sobrien		return;
51797403Sobrien	}
51897403Sobrien	/* always <digit><string of zeros> */
51997403Sobrien	ldns_buffer_printf(output, "%d", (int)mantissa);
520132720Skan	for(i=0; i<exponent-2; i++)
521132720Skan		ldns_buffer_printf(output, "0");
522132720Skan}
52397403Sobrien
52497403Sobrienldns_status
52597403Sobrienldns_rr_type2buffer_str(ldns_buffer *output, const ldns_rr_type type)
52697403Sobrien{
52797403Sobrien	const ldns_rr_descriptor *descriptor;
52897403Sobrien
529132720Skan	descriptor = ldns_rr_descript(type);
530132720Skan
531132720Skan	if (descriptor && descriptor->_name) {
53297403Sobrien		ldns_buffer_printf(output, "%s", descriptor->_name);
53397403Sobrien	} else {
534132720Skan		/* exceptions for pseudotypes */
53597403Sobrien		switch (type) {
536169691Skan			case LDNS_RR_TYPE_IXFR:
537169691Skan				ldns_buffer_printf(output, "IXFR");
538169691Skan				break;
539169691Skan			case LDNS_RR_TYPE_AXFR:
540169691Skan				ldns_buffer_printf(output, "AXFR");
54197403Sobrien				break;
54297403Sobrien			case LDNS_RR_TYPE_MAILA:
543169691Skan				ldns_buffer_printf(output, "MAILA");
544169691Skan				break;
545169691Skan			case LDNS_RR_TYPE_MAILB:
546169691Skan				ldns_buffer_printf(output, "MAILB");
547169691Skan				break;
548169691Skan			case LDNS_RR_TYPE_ANY:
549169691Skan				ldns_buffer_printf(output, "ANY");
550169691Skan				break;
551169691Skan			default:
552169691Skan				ldns_buffer_printf(output, "TYPE%u", type);
553169691Skan		}
554169691Skan	}
55597403Sobrien	return ldns_buffer_status(output);
556169691Skan}
557169691Skan
558169691Skanchar *
559169691Skanldns_rr_type2str(const ldns_rr_type type)
560169691Skan{
561169691Skan	char *str;
562169691Skan	ldns_buffer *buf;
563169691Skan
564169691Skan	buf = ldns_buffer_new(10);
565169691Skan	if (!buf) {
566169691Skan		return NULL;
567169691Skan	}
568169691Skan
569169691Skan	str = NULL;
57097403Sobrien	if (ldns_rr_type2buffer_str(buf, type) == LDNS_STATUS_OK) {
57197403Sobrien		str = ldns_buffer_export2str(buf);
57297403Sobrien	}
57397403Sobrien
57497403Sobrien	ldns_buffer_free(buf);
57597403Sobrien	return str;
57697403Sobrien}
57797403Sobrien
57897403Sobrien
57997403Sobrienldns_status
58097403Sobrienldns_rr_class2buffer_str(ldns_buffer *output,
581132720Skan                         const ldns_rr_class klass)
58297403Sobrien{
583132720Skan	ldns_lookup_table *lt;
58497403Sobrien
58597403Sobrien	lt = ldns_lookup_by_id(ldns_rr_classes, klass);
586132720Skan	if (lt) {
587132720Skan		ldns_buffer_printf(output, "%s", lt->name);
588132720Skan	} else {
58997403Sobrien		ldns_buffer_printf(output, "CLASS%d", klass);
590169691Skan	}
591169691Skan	return ldns_buffer_status(output);
59297403Sobrien}
59397403Sobrien
59497403Sobrienchar *
59597403Sobrienldns_rr_class2str(const ldns_rr_class klass)
59697403Sobrien{
59797403Sobrien	ldns_buffer *buf;
598132720Skan	char *str;
599132720Skan
600132720Skan	buf = ldns_buffer_new(10);
60197403Sobrien	if (!buf) {
60297403Sobrien		return NULL;
60397403Sobrien	}
60497403Sobrien
60597403Sobrien	str = NULL;
606132720Skan	if (ldns_rr_class2buffer_str(buf, klass) == LDNS_STATUS_OK) {
607132720Skan		str = ldns_buffer_export2str(buf);
608132720Skan	}
60997403Sobrien	ldns_buffer_free(buf);
61097403Sobrien	return str;
61197403Sobrien}
61297403Sobrien
61397403Sobrienldns_status
614132720Skanldns_rdf2buffer_str_loc(ldns_buffer *output, const ldns_rdf *rdf)
615132720Skan{
616132720Skan	/* we could do checking (ie degrees < 90 etc)? */
61797403Sobrien	uint8_t version = ldns_rdf_data(rdf)[0];
61897403Sobrien	uint8_t size;
619169691Skan	uint8_t horizontal_precision;
620169691Skan	uint8_t vertical_precision;
621169691Skan	uint32_t longitude;
622169691Skan	uint32_t latitude;
623169691Skan	uint32_t altitude;
624169691Skan	char northerness;
625169691Skan	char easterness;
626169691Skan	uint32_t h;
627169691Skan	uint32_t m;
628169691Skan	double s;
629169691Skan
630169691Skan	uint32_t equator = (uint32_t) ldns_power(2, 31);
631169691Skan
632169691Skan	if (version == 0) {
633169691Skan		size = ldns_rdf_data(rdf)[1];
634169691Skan		horizontal_precision = ldns_rdf_data(rdf)[2];
635169691Skan		vertical_precision = ldns_rdf_data(rdf)[3];
636169691Skan
637169691Skan		latitude = ldns_read_uint32(&ldns_rdf_data(rdf)[4]);
638169691Skan		longitude = ldns_read_uint32(&ldns_rdf_data(rdf)[8]);
639169691Skan		altitude = ldns_read_uint32(&ldns_rdf_data(rdf)[12]);
640169691Skan
641169691Skan		if (latitude > equator) {
642169691Skan			northerness = 'N';
643169691Skan			latitude = latitude - equator;
644169691Skan		} else {
645169691Skan			northerness = 'S';
646169691Skan			latitude = equator - latitude;
647169691Skan		}
648169691Skan		h = latitude / (1000 * 60 * 60);
649169691Skan		latitude = latitude % (1000 * 60 * 60);
650169691Skan		m = latitude / (1000 * 60);
651169691Skan		latitude = latitude % (1000 * 60);
652169691Skan		s = (double) latitude / 1000.0;
653169691Skan		ldns_buffer_printf(output, "%02u %02u %0.3f %c ",
654169691Skan			h, m, s, northerness);
655169691Skan
656169691Skan		if (longitude > equator) {
657169691Skan			easterness = 'E';
658169691Skan			longitude = longitude - equator;
659169691Skan		} else {
660169691Skan			easterness = 'W';
661169691Skan			longitude = equator - longitude;
662169691Skan		}
663169691Skan		h = longitude / (1000 * 60 * 60);
664169691Skan		longitude = longitude % (1000 * 60 * 60);
665169691Skan		m = longitude / (1000 * 60);
666169691Skan		longitude = longitude % (1000 * 60);
667169691Skan		s = (double) longitude / (1000.0);
66897403Sobrien		ldns_buffer_printf(output, "%02u %02u %0.3f %c ",
66997403Sobrien			h, m, s, easterness);
67097403Sobrien
67197403Sobrien
672132720Skan        s = ((double) altitude) / 100;
67397403Sobrien        s -= 100000;
67497403Sobrien
67597403Sobrien		if(altitude%100 != 0)
67697403Sobrien			ldns_buffer_printf(output, "%.2f", s);
67797403Sobrien        else
678169691Skan			ldns_buffer_printf(output, "%.0f", s);
67997403Sobrien
680132720Skan		ldns_buffer_printf(output, "m ");
68197403Sobrien
68297403Sobrien		loc_cm_print(output, (size & 0xf0) >> 4, size & 0x0f);
68397403Sobrien		ldns_buffer_printf(output, "m ");
68497403Sobrien
68597403Sobrien		loc_cm_print(output, (horizontal_precision & 0xf0) >> 4,
68697403Sobrien			horizontal_precision & 0x0f);
68797403Sobrien		ldns_buffer_printf(output, "m ");
688132720Skan
68997403Sobrien		loc_cm_print(output, (vertical_precision & 0xf0) >> 4,
69097403Sobrien			vertical_precision & 0x0f);
69197403Sobrien		ldns_buffer_printf(output, "m");
69297403Sobrien
69397403Sobrien		return ldns_buffer_status(output);
69497403Sobrien	} else {
69597403Sobrien		return ldns_rdf2buffer_str_hex(output, rdf);
69697403Sobrien	}
69797403Sobrien}
69897403Sobrien
69997403Sobrienldns_status
70097403Sobrienldns_rdf2buffer_str_unknown(ldns_buffer *output, const ldns_rdf *rdf)
70197403Sobrien{
70297403Sobrien	ldns_buffer_printf(output, "\\# %u ", ldns_rdf_size(rdf));
70397403Sobrien	return ldns_rdf2buffer_str_hex(output, rdf);
704132720Skan}
705132720Skan
706132720Skanldns_status
707132720Skanldns_rdf2buffer_str_nsap(ldns_buffer *output, const ldns_rdf *rdf)
70897403Sobrien{
70997403Sobrien	ldns_buffer_printf(output, "0x");
710132720Skan	return ldns_rdf2buffer_str_hex(output, rdf);
711132720Skan}
712146897Skan
713146897Skanldns_status
714132720Skanldns_rdf2buffer_str_atma(ldns_buffer *output, const ldns_rdf *rdf)
715132720Skan{
71697403Sobrien	return ldns_rdf2buffer_str_hex(output, rdf);
717132720Skan}
718132720Skan
719132720Skanldns_status
720132720Skanldns_rdf2buffer_str_wks(ldns_buffer *output, const ldns_rdf *rdf)
721132720Skan{
722132720Skan	/* protocol, followed by bitmap of services */
72397403Sobrien	struct protoent *protocol;
72497403Sobrien	char *proto_name = NULL;
72597403Sobrien	uint8_t protocol_nr;
72697403Sobrien	struct servent *service;
72797403Sobrien	uint16_t current_service;
72897403Sobrien
72997403Sobrien	protocol_nr = ldns_rdf_data(rdf)[0];
73097403Sobrien	protocol = getprotobynumber((int) protocol_nr);
73197403Sobrien	if (protocol && (protocol->p_name != NULL)) {
73297403Sobrien		proto_name = protocol->p_name;
73397403Sobrien		ldns_buffer_printf(output, "%s ", protocol->p_name);
73497403Sobrien	} else {
73597403Sobrien		ldns_buffer_printf(output, "%u ", protocol_nr);
73697403Sobrien	}
73797403Sobrien
73897403Sobrien#ifdef HAVE_ENDPROTOENT
739132720Skan	endprotoent();
740132720Skan#endif
741132720Skan
742132720Skan	for (current_service = 0;
743132720Skan	     current_service < ldns_rdf_size(rdf) * 7; current_service++) {
74497403Sobrien		if (ldns_get_bit(&(ldns_rdf_data(rdf)[1]), current_service)) {
74597403Sobrien			service = getservbyport((int) htons(current_service),
746132720Skan			                        proto_name);
747132720Skan			if (service && service->s_name) {
748132720Skan				ldns_buffer_printf(output, "%s ", service->s_name);
74997403Sobrien			} else {
750132720Skan				ldns_buffer_printf(output, "%u ", current_service);
751132720Skan			}
752132720Skan#ifdef HAVE_ENDSERVENT
753132720Skan			endservent();
754132720Skan#endif
755132720Skan		}
75697403Sobrien	}
75797403Sobrien	return ldns_buffer_status(output);
75897403Sobrien}
75997403Sobrien
76097403Sobrienldns_status
76197403Sobrienldns_rdf2buffer_str_nsec(ldns_buffer *output, const ldns_rdf *rdf)
76297403Sobrien{
76397403Sobrien	/* Note: this code is duplicated in higher.c in
76497403Sobrien	 * ldns_nsec_type_check() function
76597403Sobrien	 */
76697403Sobrien	uint8_t window_block_nr;
76797403Sobrien	uint8_t bitmap_length;
76897403Sobrien	uint16_t type;
769132720Skan	uint16_t pos = 0;
77097403Sobrien	uint16_t bit_pos;
771132720Skan	uint8_t *data = ldns_rdf_data(rdf);
772132720Skan	const ldns_rr_descriptor *descriptor;
77397403Sobrien
77497403Sobrien	while(pos < ldns_rdf_size(rdf)) {
775132720Skan		window_block_nr = data[pos];
776132720Skan		bitmap_length = data[pos + 1];
777132720Skan		pos += 2;
778132720Skan
779132720Skan		for (bit_pos = 0; bit_pos < (bitmap_length) * 8; bit_pos++) {
780132720Skan			if (ldns_get_bit(&data[pos], bit_pos)) {
781169691Skan				type = 256 * (uint16_t) window_block_nr + bit_pos;
782169691Skan				descriptor = ldns_rr_descript(type);
78397403Sobrien
78497403Sobrien				if (descriptor && descriptor->_name) {
78597403Sobrien					ldns_buffer_printf(output, "%s ",
78697403Sobrien							descriptor->_name);
78797403Sobrien				} else {
78897403Sobrien					ldns_buffer_printf(output, "TYPE%u ", type);
78997403Sobrien				}
79097403Sobrien			}
79197403Sobrien		}
79297403Sobrien
79397403Sobrien		pos += (uint16_t) bitmap_length;
79497403Sobrien	}
79597403Sobrien
79697403Sobrien	return ldns_buffer_status(output);
79797403Sobrien}
79897403Sobrien
79997403Sobrienldns_status
80097403Sobrienldns_rdf2buffer_str_nsec3_salt(ldns_buffer *output, const ldns_rdf *rdf)
801132720Skan{
802132720Skan	uint8_t salt_length;
80397403Sobrien	uint8_t salt_pos;
804132720Skan
805132720Skan	uint8_t *data = ldns_rdf_data(rdf);
80697403Sobrien
80797403Sobrien        if(ldns_rdf_size(rdf) == 0) {
80897403Sobrien                output->_status = LDNS_STATUS_ERR;
809132720Skan	        return ldns_buffer_status(output);
810132720Skan        }
811132720Skan	salt_length = data[0];
81297403Sobrien	/* from now there are variable length entries so remember pos */
813169691Skan	if (salt_length == 0 || ((size_t)salt_length)+1 > ldns_rdf_size(rdf)) {
81497403Sobrien		ldns_buffer_printf(output, "- ");
81597403Sobrien	} else {
81697403Sobrien		for (salt_pos = 0; salt_pos < salt_length; salt_pos++) {
81797403Sobrien			ldns_buffer_printf(output, "%02x", data[1 + salt_pos]);
81897403Sobrien		}
81997403Sobrien		ldns_buffer_printf(output, " ");
82097403Sobrien	}
82197403Sobrien
82297403Sobrien	return ldns_buffer_status(output);
82397403Sobrien}
82497403Sobrien
82597403Sobrienldns_status
82697403Sobrienldns_rdf2buffer_str_period(ldns_buffer *output, const ldns_rdf *rdf)
82797403Sobrien{
82897403Sobrien	/* period is the number of seconds */
82997403Sobrien	uint32_t p = ldns_read_uint32(ldns_rdf_data(rdf));
83097403Sobrien	ldns_buffer_printf(output, "%u", p);
83197403Sobrien	return ldns_buffer_status(output);
83297403Sobrien}
833132720Skan
83497403Sobrienldns_status
835132720Skanldns_rdf2buffer_str_tsigtime(ldns_buffer *output,const  ldns_rdf *rdf)
836132720Skan{
83797403Sobrien	/* tsigtime is 48 bits network order unsigned integer */
83897403Sobrien	uint64_t tsigtime = 0;
839132720Skan	uint8_t *data = ldns_rdf_data(rdf);
840132720Skan
841146897Skan	if (ldns_rdf_size(rdf) != 6) {
842146897Skan		return LDNS_STATUS_ERR;
843146897Skan	}
844146897Skan
845146897Skan	tsigtime = ldns_read_uint16(data);
846132720Skan	tsigtime *= 65536;
847132720Skan	tsigtime += ldns_read_uint16(data+2);
848132720Skan	tsigtime *= 65536;
84997403Sobrien
850169691Skan	ldns_buffer_printf(output, "%llu ", tsigtime);
851169691Skan
852132720Skan	return ldns_buffer_status(output);
853132720Skan}
854132720Skan
855132720Skanldns_status
856132720Skanldns_rdf2buffer_str_apl(ldns_buffer *output, const ldns_rdf *rdf)
857132720Skan{
85897403Sobrien	uint8_t *data = ldns_rdf_data(rdf);
85997403Sobrien	uint16_t address_family;
86097403Sobrien	uint8_t prefix;
86197403Sobrien	bool negation;
86297403Sobrien	uint8_t adf_length;
86397403Sobrien	size_t i;
86497403Sobrien	size_t pos = 0;
86597403Sobrien
86697403Sobrien	while (pos < (unsigned int) ldns_rdf_size(rdf)) {
86797403Sobrien                if(pos + 3 >= (unsigned)ldns_rdf_size(rdf))
86897403Sobrien                        return LDNS_STATUS_SYNTAX_RDATA_ERR;
86997403Sobrien		address_family = ldns_read_uint16(&data[pos]);
87097403Sobrien		prefix = data[pos + 2];
87197403Sobrien		negation = data[pos + 3] & LDNS_APL_NEGATION;
87297403Sobrien		adf_length = data[pos + 3] & LDNS_APL_MASK;
873132720Skan		if (address_family == LDNS_APL_IP4) {
874132720Skan			/* check if prefix < 32? */
87597403Sobrien			if (negation) {
876132720Skan				ldns_buffer_printf(output, "!");
877132720Skan			}
87897403Sobrien			ldns_buffer_printf(output, "%u:", address_family);
87997403Sobrien			/* address is variable length 0 - 4 */
88097403Sobrien			for (i = 0; i < 4; i++) {
881132720Skan				if (i > 0) {
882132720Skan					ldns_buffer_printf(output, ".");
883132720Skan				}
884132720Skan				if (i < (unsigned short) adf_length) {
88597403Sobrien                                        if(pos+i+4 >= ldns_rdf_size(rdf))
886169691Skan                                                return LDNS_STATUS_SYNTAX_RDATA_ERR;
887169691Skan					ldns_buffer_printf(output, "%d",
888132720Skan					                   data[pos + i + 4]);
889132720Skan				} else {
890132720Skan					ldns_buffer_printf(output, "0");
891132720Skan				}
892132720Skan			}
893132720Skan			ldns_buffer_printf(output, "/%u ", prefix);
89497403Sobrien		} else if (address_family == LDNS_APL_IP6) {
89597403Sobrien			/* check if prefix < 128? */
89697403Sobrien			if (negation) {
897132720Skan				ldns_buffer_printf(output, "!");
898132720Skan			}
899132720Skan			ldns_buffer_printf(output, "%u:", address_family);
900132720Skan			/* address is variable length 0 - 16 */
901132720Skan			for (i = 0; i < 16; i++) {
90297403Sobrien				if (i % 2 == 0 && i > 0) {
903132720Skan					ldns_buffer_printf(output, ":");
904132720Skan				}
905132720Skan				if (i < (unsigned short) adf_length) {
90697403Sobrien                                        if(pos+i+4 >= ldns_rdf_size(rdf))
90797403Sobrien                                                return LDNS_STATUS_SYNTAX_RDATA_ERR;
908132720Skan					ldns_buffer_printf(output, "%02x",
909132720Skan					                   data[pos + i + 4]);
91097403Sobrien				} else {
91197403Sobrien					ldns_buffer_printf(output, "00");
91297403Sobrien				}
91397403Sobrien			}
91497403Sobrien			ldns_buffer_printf(output, "/%u ", prefix);
91597403Sobrien
91697403Sobrien		} else {
917132720Skan			/* unknown address family */
918132720Skan			ldns_buffer_printf(output, "Unknown address family: %u data: ",
919132720Skan					address_family);
92097403Sobrien			for (i = 1; i < (unsigned short) (4 + adf_length); i++) {
921132720Skan                                if(pos+i >= ldns_rdf_size(rdf))
922132720Skan                                        return LDNS_STATUS_SYNTAX_RDATA_ERR;
923132720Skan				ldns_buffer_printf(output, "%02x", data[i]);
924132720Skan			}
92597403Sobrien		}
926132720Skan		pos += 4 + adf_length;
927132720Skan	}
928132720Skan	return ldns_buffer_status(output);
929132720Skan}
93097403Sobrien
93197403Sobrienldns_status
93297403Sobrienldns_rdf2buffer_str_int16_data(ldns_buffer *output, const ldns_rdf *rdf)
933169691Skan{
93497403Sobrien	/* Subtract the size (2) of the number that specifies the length */
935132720Skan	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