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#include <ldns/internal.h>
17
18#include <limits.h>
19
20#ifdef HAVE_SYS_SOCKET_H
21#include <sys/socket.h>
22#endif
23#ifdef HAVE_ARPA_INET_H
24#include <arpa/inet.h>
25#endif
26#ifdef HAVE_NETDB_H
27#include <netdb.h>
28#endif
29#include <time.h>
30#include <sys/time.h>
31
32#ifdef HAVE_SSL
33#include <openssl/bn.h>
34#include <openssl/rsa.h>
35#ifdef USE_DSA
36#include <openssl/dsa.h>
37#endif
38#endif
39
40#ifndef INET_ADDRSTRLEN
41#define INET_ADDRSTRLEN 16
42#endif
43#ifndef INET6_ADDRSTRLEN
44#define INET6_ADDRSTRLEN 46
45#endif
46
47/* lookup tables for standard DNS stuff  */
48
49/* Taken from RFC 2535, section 7.  */
50ldns_lookup_table ldns_algorithms[] = {
51        { LDNS_RSAMD5, "RSAMD5" },
52        { LDNS_DH, "DH" },
53        { LDNS_DSA, "DSA" },
54        { LDNS_ECC, "ECC" },
55        { LDNS_RSASHA1, "RSASHA1" },
56        { LDNS_DSA_NSEC3, "DSA-NSEC3-SHA1" },
57        { LDNS_RSASHA1_NSEC3, "RSASHA1-NSEC3-SHA1" },
58	{ LDNS_RSASHA256, "RSASHA256"},
59	{ LDNS_RSASHA512, "RSASHA512"},
60	{ LDNS_ECC_GOST, "ECC-GOST"},
61        { LDNS_ECDSAP256SHA256, "ECDSAP256SHA256"},
62        { LDNS_ECDSAP384SHA384, "ECDSAP384SHA384"},
63	{ LDNS_ED25519, "ED25519"},
64	{ LDNS_ED448, "ED448"},
65        { LDNS_INDIRECT, "INDIRECT" },
66        { LDNS_PRIVATEDNS, "PRIVATEDNS" },
67        { LDNS_PRIVATEOID, "PRIVATEOID" },
68        { 0, NULL }
69};
70
71/* Hashing algorithms used in the DS record */
72ldns_lookup_table ldns_hashes[] = {
73        {LDNS_SHA1     , "SHA1" },      /* RFC 4034 */
74        {LDNS_SHA256   , "SHA256" },    /* RFC 4509 */
75        {LDNS_HASH_GOST, "HASH-GOST" }, /* RFC 5933 */
76        {LDNS_SHA384   , "SHA384" },    /* RFC 6605 */
77        { 0, NULL }
78};
79
80/* Taken from RFC 4398  */
81ldns_lookup_table ldns_cert_algorithms[] = {
82        { LDNS_CERT_PKIX, "PKIX" },
83        { LDNS_CERT_SPKI, "SPKI" },
84        { LDNS_CERT_PGP, "PGP" },
85        { LDNS_CERT_IPKIX, "IPKIX" },
86        { LDNS_CERT_ISPKI, "ISPKI" },
87        { LDNS_CERT_IPGP, "IPGP" },
88        { LDNS_CERT_ACPKIX, "ACPKIX" },
89        { LDNS_CERT_IACPKIX, "IACPKIX" },
90        { LDNS_CERT_URI, "URI" },
91        { LDNS_CERT_OID, "OID" },
92        { 0, NULL }
93};
94
95/* classes  */
96ldns_lookup_table ldns_rr_classes[] = {
97        { LDNS_RR_CLASS_IN, "IN" },
98        { LDNS_RR_CLASS_CH, "CH" },
99        { LDNS_RR_CLASS_HS, "HS" },
100        { LDNS_RR_CLASS_NONE, "NONE" },
101        { LDNS_RR_CLASS_ANY, "ANY" },
102        { 0, NULL }
103};
104
105/* if these are used elsewhere */
106ldns_lookup_table ldns_rcodes[] = {
107        { LDNS_RCODE_NOERROR, "NOERROR" },
108        { LDNS_RCODE_FORMERR, "FORMERR" },
109        { LDNS_RCODE_SERVFAIL, "SERVFAIL" },
110        { LDNS_RCODE_NXDOMAIN, "NXDOMAIN" },
111        { LDNS_RCODE_NOTIMPL, "NOTIMPL" },
112        { LDNS_RCODE_REFUSED, "REFUSED" },
113        { LDNS_RCODE_YXDOMAIN, "YXDOMAIN" },
114        { LDNS_RCODE_YXRRSET, "YXRRSET" },
115        { LDNS_RCODE_NXRRSET, "NXRRSET" },
116        { LDNS_RCODE_NOTAUTH, "NOTAUTH" },
117        { LDNS_RCODE_NOTZONE, "NOTZONE" },
118        { 0, NULL }
119};
120
121ldns_lookup_table ldns_opcodes[] = {
122        { LDNS_PACKET_QUERY, "QUERY" },
123        { LDNS_PACKET_IQUERY, "IQUERY" },
124        { LDNS_PACKET_STATUS, "STATUS" },
125	{ LDNS_PACKET_NOTIFY, "NOTIFY" },
126	{ LDNS_PACKET_UPDATE, "UPDATE" },
127        { 0, NULL }
128};
129
130const ldns_output_format   ldns_output_format_nocomments_record = { 0, NULL };
131const ldns_output_format  *ldns_output_format_nocomments
132			= &ldns_output_format_nocomments_record;
133const ldns_output_format   ldns_output_format_onlykeyids_record = {
134	LDNS_COMMENT_KEY, NULL
135};
136const ldns_output_format  *ldns_output_format_onlykeyids
137			= &ldns_output_format_onlykeyids_record;
138const ldns_output_format  *ldns_output_format_default
139			= &ldns_output_format_onlykeyids_record;
140
141const ldns_output_format   ldns_output_format_bubblebabble_record = {
142	LDNS_COMMENT_KEY | LDNS_COMMENT_BUBBLEBABBLE | LDNS_COMMENT_FLAGS, NULL
143};
144const ldns_output_format  *ldns_output_format_bubblebabble
145			= &ldns_output_format_bubblebabble_record;
146
147static bool
148ldns_output_format_covers_type(const ldns_output_format* fmt, ldns_rr_type t)
149{
150	return fmt && (fmt->flags & LDNS_FMT_RFC3597) &&
151		((ldns_output_format_storage*)fmt)->bitmap &&
152		ldns_nsec_bitmap_covers_type(
153				((ldns_output_format_storage*)fmt)->bitmap, t);
154}
155
156ldns_status
157ldns_output_format_set_type(ldns_output_format* fmt, ldns_rr_type t)
158{
159	ldns_output_format_storage* fmt_st = (ldns_output_format_storage*)fmt;
160	ldns_status s;
161
162	assert(fmt != NULL);
163
164	if (!(fmt_st->flags & LDNS_FMT_RFC3597)) {
165		ldns_output_format_set(fmt, LDNS_FMT_RFC3597);
166	}
167	if (! fmt_st->bitmap) {
168		s = ldns_rdf_bitmap_known_rr_types_space(&fmt_st->bitmap);
169		if (s != LDNS_STATUS_OK) {
170			return s;
171		}
172	}
173	return ldns_nsec_bitmap_set_type(fmt_st->bitmap, t);
174}
175
176ldns_status
177ldns_output_format_clear_type(ldns_output_format* fmt, ldns_rr_type t)
178{
179	ldns_output_format_storage* fmt_st = (ldns_output_format_storage*)fmt;
180	ldns_status s;
181
182	assert(fmt != NULL);
183
184	if (!(fmt_st->flags & LDNS_FMT_RFC3597)) {
185		ldns_output_format_set(fmt, LDNS_FMT_RFC3597);
186	}
187	if (! fmt_st->bitmap) {
188		s = ldns_rdf_bitmap_known_rr_types(&fmt_st->bitmap);
189		if (s != LDNS_STATUS_OK) {
190			return s;
191		}
192	}
193	return ldns_nsec_bitmap_clear_type(fmt_st->bitmap, t);
194}
195
196ldns_status
197ldns_pkt_opcode2buffer_str(ldns_buffer *output, ldns_pkt_opcode opcode)
198{
199	ldns_lookup_table *lt = ldns_lookup_by_id(ldns_opcodes, opcode);
200	if (lt && lt->name) {
201		ldns_buffer_printf(output, "%s", lt->name);
202	} else {
203		ldns_buffer_printf(output, "OPCODE%u", opcode);
204	}
205	return ldns_buffer_status(output);
206}
207
208ldns_status
209ldns_pkt_rcode2buffer_str(ldns_buffer *output, ldns_pkt_rcode rcode)
210{
211	ldns_lookup_table *lt = ldns_lookup_by_id(ldns_rcodes, rcode);
212	if (lt && lt->name) {
213		ldns_buffer_printf(output, "%s", lt->name);
214	} else {
215		ldns_buffer_printf(output, "RCODE%u", rcode);
216	}
217	return ldns_buffer_status(output);
218}
219
220ldns_status
221ldns_algorithm2buffer_str(ldns_buffer *output,
222                          ldns_algorithm algorithm)
223{
224	ldns_lookup_table *lt = ldns_lookup_by_id(ldns_algorithms,
225	                                          algorithm);
226	if (lt && lt->name) {
227		ldns_buffer_printf(output, "%s", lt->name);
228	} else {
229		ldns_buffer_printf(output, "ALG%u", algorithm);
230	}
231	return ldns_buffer_status(output);
232}
233
234ldns_status
235ldns_cert_algorithm2buffer_str(ldns_buffer *output,
236                               ldns_cert_algorithm cert_algorithm)
237{
238	ldns_lookup_table *lt = ldns_lookup_by_id(ldns_cert_algorithms,
239	                                          cert_algorithm);
240	if (lt && lt->name) {
241		ldns_buffer_printf(output, "%s", lt->name);
242	} else {
243		ldns_buffer_printf(output, "CERT_ALG%u",
244		                   cert_algorithm);
245	}
246	return ldns_buffer_status(output);
247}
248
249char *
250ldns_pkt_opcode2str(ldns_pkt_opcode opcode)
251{
252	char *str;
253	ldns_buffer *buf;
254
255	buf = ldns_buffer_new(12);
256	if (!buf) {
257		return NULL;
258	}
259
260	str = NULL;
261	if (ldns_pkt_opcode2buffer_str(buf, opcode) == LDNS_STATUS_OK) {
262		str = ldns_buffer_export2str(buf);
263	}
264
265	ldns_buffer_free(buf);
266	return str;
267}
268
269char *
270ldns_pkt_rcode2str(ldns_pkt_rcode rcode)
271{
272	char *str;
273	ldns_buffer *buf;
274
275	buf = ldns_buffer_new(10);
276	if (!buf) {
277		return NULL;
278	}
279
280	str = NULL;
281	if (ldns_pkt_rcode2buffer_str(buf, rcode) == LDNS_STATUS_OK) {
282		str = ldns_buffer_export2str(buf);
283	}
284
285	ldns_buffer_free(buf);
286	return str;
287}
288
289char *
290ldns_pkt_algorithm2str(ldns_algorithm algorithm)
291{
292	char *str;
293	ldns_buffer *buf;
294
295	buf = ldns_buffer_new(10);
296	if (!buf) {
297		return NULL;
298	}
299
300	str = NULL;
301	if (ldns_algorithm2buffer_str(buf, algorithm)
302	    == LDNS_STATUS_OK) {
303		str = ldns_buffer_export2str(buf);
304	}
305
306	ldns_buffer_free(buf);
307	return str;
308}
309
310char *
311ldns_pkt_cert_algorithm2str(ldns_cert_algorithm cert_algorithm)
312{
313	char *str;
314	ldns_buffer *buf;
315
316	buf = ldns_buffer_new(10);
317	if (!buf) {
318		return NULL;
319	}
320
321	str = NULL;
322	if (ldns_cert_algorithm2buffer_str(buf, cert_algorithm)
323	    == LDNS_STATUS_OK) {
324		str = ldns_buffer_export2str(buf);
325	}
326
327	ldns_buffer_free(buf);
328	return str;
329}
330
331
332/* do NOT pass compressed data here :p */
333ldns_status
334ldns_rdf2buffer_str_dname(ldns_buffer *output, const ldns_rdf *dname)
335{
336	/* can we do with 1 pos var? or without at all? */
337	uint8_t src_pos = 0;
338	uint8_t len;
339	uint8_t *data;
340	uint8_t i;
341	unsigned char c;
342
343	data = (uint8_t*)ldns_rdf_data(dname);
344	len = data[src_pos];
345
346	if (ldns_rdf_size(dname) > LDNS_MAX_DOMAINLEN) {
347		/* too large, return */
348		return LDNS_STATUS_DOMAINNAME_OVERFLOW;
349	}
350
351	/* special case: root label */
352	if (1 == ldns_rdf_size(dname)) {
353		ldns_buffer_printf(output, ".");
354	} else {
355		while ((len > 0) && src_pos < ldns_rdf_size(dname)) {
356			src_pos++;
357			for(i = 0; i < len; i++) {
358				/* paranoia check for various 'strange'
359				   characters in dnames
360				*/
361				c = (unsigned char) data[src_pos];
362				if(c == '.' || c == ';' ||
363				   c == '(' || c == ')' ||
364				   c == '\\') {
365					ldns_buffer_printf(output, "\\%c",
366							data[src_pos]);
367				} else if (!(isascii(c) && isgraph(c))) {
368					ldns_buffer_printf(output, "\\%03u",
369						        data[src_pos]);
370				} else {
371					ldns_buffer_printf(output, "%c", data[src_pos]);
372				}
373				src_pos++;
374			}
375
376			if (src_pos < ldns_rdf_size(dname)) {
377				ldns_buffer_printf(output, ".");
378			}
379			len = data[src_pos];
380		}
381	}
382	return ldns_buffer_status(output);
383}
384
385ldns_status
386ldns_rdf2buffer_str_int8(ldns_buffer *output, const ldns_rdf *rdf)
387{
388	uint8_t data = ldns_rdf_data(rdf)[0];
389	ldns_buffer_printf(output, "%lu", (unsigned long) data);
390	return ldns_buffer_status(output);
391}
392
393ldns_status
394ldns_rdf2buffer_str_int16(ldns_buffer *output, const ldns_rdf *rdf)
395{
396	uint16_t data = ldns_read_uint16(ldns_rdf_data(rdf));
397	ldns_buffer_printf(output, "%lu", (unsigned long) data);
398	return ldns_buffer_status(output);
399}
400
401ldns_status
402ldns_rdf2buffer_str_int32(ldns_buffer *output, const ldns_rdf *rdf)
403{
404	uint32_t data = ldns_read_uint32(ldns_rdf_data(rdf));
405	ldns_buffer_printf(output, "%lu", (unsigned long) data);
406	return ldns_buffer_status(output);
407}
408
409ldns_status
410ldns_rdf2buffer_str_time(ldns_buffer *output, const ldns_rdf *rdf)
411{
412	/* create a YYYYMMDDHHMMSS string if possible */
413	struct tm tm;
414	char date_buf[16];
415
416	memset(&tm, 0, sizeof(tm));
417	if (ldns_serial_arithmetics_gmtime_r(ldns_rdf2native_int32(rdf), time(NULL), &tm)
418	    && strftime(date_buf, 15, "%Y%m%d%H%M%S", &tm)) {
419		ldns_buffer_printf(output, "%s", date_buf);
420	}
421	return ldns_buffer_status(output);
422}
423
424ldns_status
425ldns_rdf2buffer_str_a(ldns_buffer *output, const ldns_rdf *rdf)
426{
427	char str[INET_ADDRSTRLEN];
428
429	if (inet_ntop(AF_INET, ldns_rdf_data(rdf), str, INET_ADDRSTRLEN)) {
430		ldns_buffer_printf(output, "%s", str);
431	}
432	return ldns_buffer_status(output);
433}
434
435ldns_status
436ldns_rdf2buffer_str_aaaa(ldns_buffer *output, const ldns_rdf *rdf)
437{
438	char str[INET6_ADDRSTRLEN];
439
440	if (inet_ntop(AF_INET6, ldns_rdf_data(rdf), str, INET6_ADDRSTRLEN)) {
441		ldns_buffer_printf(output, "%s", str);
442	}
443
444	return ldns_buffer_status(output);
445}
446
447static void
448ldns_characters2buffer_str(ldns_buffer* output,
449		size_t amount, const uint8_t* characters)
450{
451	uint8_t ch;
452	while (amount > 0) {
453		ch = *characters++;
454		if (isprint((int)ch) || ch == '\t') {
455			if (ch == '\"' || ch == '\\')
456				ldns_buffer_printf(output, "\\%c", ch);
457			else
458				ldns_buffer_printf(output, "%c", ch);
459		} else {
460			ldns_buffer_printf(output, "\\%03u",
461                                (unsigned)(uint8_t) ch);
462		}
463		amount--;
464	}
465}
466
467ldns_status
468ldns_rdf2buffer_str_str(ldns_buffer *output, const ldns_rdf *rdf)
469{
470        if(ldns_rdf_size(rdf) < 1) {
471                return LDNS_STATUS_WIRE_RDATA_ERR;
472        }
473        if((int)ldns_rdf_size(rdf) < (int)ldns_rdf_data(rdf)[0] + 1) {
474                return LDNS_STATUS_WIRE_RDATA_ERR;
475        }
476	ldns_buffer_printf(output, "\"");
477	ldns_characters2buffer_str(output,
478			ldns_rdf_data(rdf)[0], ldns_rdf_data(rdf) + 1);
479	ldns_buffer_printf(output, "\"");
480	return ldns_buffer_status(output);
481}
482
483ldns_status
484ldns_rdf2buffer_str_b64(ldns_buffer *output, const ldns_rdf *rdf)
485{
486	size_t size;
487	char *b64;
488
489	if (ldns_rdf_size(rdf) == 0) {
490		ldns_buffer_printf(output, "0");
491		return ldns_buffer_status(output);
492	} else
493		size = ldns_b64_ntop_calculate_size(ldns_rdf_size(rdf));
494
495	if (!(b64 = LDNS_XMALLOC(char, size)))
496		return LDNS_STATUS_MEM_ERR;
497
498	if (ldns_b64_ntop(ldns_rdf_data(rdf), ldns_rdf_size(rdf), b64, size)) {
499		ldns_buffer_printf(output, "%s", b64);
500	}
501	LDNS_FREE(b64);
502	return ldns_buffer_status(output);
503}
504
505ldns_status
506ldns_rdf2buffer_str_b32_ext(ldns_buffer *output, const ldns_rdf *rdf)
507{
508	size_t size;
509	char *b32;
510	if(ldns_rdf_size(rdf) == 0)
511		return LDNS_STATUS_OK;
512        /* remove -1 for the b32-hash-len octet */
513	size = ldns_b32_ntop_calculate_size(ldns_rdf_size(rdf) - 1);
514        /* add one for the end nul for the string */
515	b32 = LDNS_XMALLOC(char, size + 1);
516	if(!b32) return LDNS_STATUS_MEM_ERR;
517	size = (size_t) ldns_b32_ntop_extended_hex(ldns_rdf_data(rdf) + 1,
518		ldns_rdf_size(rdf) - 1, b32, size+1);
519	if (size > 0) {
520		ldns_buffer_printf(output, "%s", b32);
521	}
522	LDNS_FREE(b32);
523	return ldns_buffer_status(output);
524}
525
526ldns_status
527ldns_rdf2buffer_str_hex(ldns_buffer *output, const ldns_rdf *rdf)
528{
529	size_t i;
530	for (i = 0; i < ldns_rdf_size(rdf); i++) {
531		ldns_buffer_printf(output, "%02x", ldns_rdf_data(rdf)[i]);
532	}
533
534	return ldns_buffer_status(output);
535}
536
537static ldns_status
538ldns_rdf2buffer_str_type_fmt(ldns_buffer *output,
539		const ldns_output_format* fmt, const ldns_rdf *rdf)
540{
541        uint16_t data = ldns_read_uint16(ldns_rdf_data(rdf));
542
543	if (! ldns_output_format_covers_type(fmt, data) &&
544			ldns_rr_descript(data) &&
545			ldns_rr_descript(data)->_name) {
546
547		ldns_buffer_printf(output, "%s",ldns_rr_descript(data)->_name);
548	} else {
549		ldns_buffer_printf(output, "TYPE%u", data);
550	}
551	return  ldns_buffer_status(output);
552}
553
554ldns_status
555ldns_rdf2buffer_str_type(ldns_buffer *output, const ldns_rdf *rdf)
556{
557	return ldns_rdf2buffer_str_type_fmt(output,
558			ldns_output_format_default, rdf);
559}
560
561ldns_status
562ldns_rdf2buffer_str_class(ldns_buffer *output, const ldns_rdf *rdf)
563{
564	uint16_t data = ldns_read_uint16(ldns_rdf_data(rdf));
565	ldns_lookup_table *lt;
566
567 	lt = ldns_lookup_by_id(ldns_rr_classes, (int) data);
568	if (lt) {
569		ldns_buffer_printf(output, "\t%s", lt->name);
570	} else {
571		ldns_buffer_printf(output, "\tCLASS%d", data);
572	}
573	return ldns_buffer_status(output);
574}
575
576ldns_status
577ldns_rdf2buffer_str_cert_alg(ldns_buffer *output, const ldns_rdf *rdf)
578{
579        uint16_t data = ldns_read_uint16(ldns_rdf_data(rdf));
580	ldns_lookup_table *lt;
581 	lt = ldns_lookup_by_id(ldns_cert_algorithms, (int) data);
582	if (lt) {
583		ldns_buffer_printf(output, "%s", lt->name);
584	} else {
585		ldns_buffer_printf(output, "%d", data);
586	}
587	return ldns_buffer_status(output);
588}
589
590ldns_status
591ldns_rdf2buffer_str_alg(ldns_buffer *output, const ldns_rdf *rdf)
592{
593	return ldns_rdf2buffer_str_int8(output, rdf);
594}
595
596static void
597loc_cm_print(ldns_buffer *output, uint8_t mantissa, uint8_t exponent)
598{
599	uint8_t i;
600	/* is it 0.<two digits> ? */
601	if(exponent < 2) {
602		if(exponent == 1)
603			mantissa *= 10;
604		ldns_buffer_printf(output, "0.%02ld", (long)mantissa);
605		return;
606	}
607	/* always <digit><string of zeros> */
608	ldns_buffer_printf(output, "%d", (int)mantissa);
609	for(i=0; i<exponent-2; i++)
610		ldns_buffer_printf(output, "0");
611}
612
613ldns_status
614ldns_rr_type2buffer_str(ldns_buffer *output, const ldns_rr_type type)
615{
616	const ldns_rr_descriptor *descriptor;
617
618	descriptor = ldns_rr_descript(type);
619
620	switch (type) {
621		case LDNS_RR_TYPE_IXFR:
622			ldns_buffer_printf(output, "IXFR");
623			break;
624		case LDNS_RR_TYPE_AXFR:
625			ldns_buffer_printf(output, "AXFR");
626			break;
627		case LDNS_RR_TYPE_MAILA:
628			ldns_buffer_printf(output, "MAILA");
629			break;
630		case LDNS_RR_TYPE_MAILB:
631			ldns_buffer_printf(output, "MAILB");
632			break;
633		case LDNS_RR_TYPE_ANY:
634			ldns_buffer_printf(output, "ANY");
635			break;
636		default:
637			if (descriptor && descriptor->_name) {
638				ldns_buffer_printf(output, "%s", descriptor->_name);
639			} else {
640				ldns_buffer_printf(output, "TYPE%u", type);
641			}
642	}
643	return ldns_buffer_status(output);
644}
645
646char *
647ldns_rr_type2str(const ldns_rr_type type)
648{
649	char *str;
650	ldns_buffer *buf;
651
652	buf = ldns_buffer_new(10);
653	if (!buf) {
654		return NULL;
655	}
656
657	str = NULL;
658	if (ldns_rr_type2buffer_str(buf, type) == LDNS_STATUS_OK) {
659		str = ldns_buffer_export2str(buf);
660	}
661
662	ldns_buffer_free(buf);
663	return str;
664}
665
666
667ldns_status
668ldns_rr_class2buffer_str(ldns_buffer *output,
669                         const ldns_rr_class klass)
670{
671	ldns_lookup_table *lt;
672
673	lt = ldns_lookup_by_id(ldns_rr_classes, klass);
674	if (lt) {
675		ldns_buffer_printf(output, "%s", lt->name);
676	} else {
677		ldns_buffer_printf(output, "CLASS%d", klass);
678	}
679	return ldns_buffer_status(output);
680}
681
682char *
683ldns_rr_class2str(const ldns_rr_class klass)
684{
685	ldns_buffer *buf;
686	char *str;
687
688	buf = ldns_buffer_new(10);
689	if (!buf) {
690		return NULL;
691	}
692
693	str = NULL;
694	if (ldns_rr_class2buffer_str(buf, klass) == LDNS_STATUS_OK) {
695		str = ldns_buffer_export2str(buf);
696	}
697	ldns_buffer_free(buf);
698	return str;
699}
700
701ldns_status
702ldns_rdf2buffer_str_loc(ldns_buffer *output, const ldns_rdf *rdf)
703{
704	/* we could do checking (ie degrees < 90 etc)? */
705	uint8_t version;
706	uint8_t size;
707	uint8_t horizontal_precision;
708	uint8_t vertical_precision;
709	uint32_t longitude;
710	uint32_t latitude;
711	uint32_t altitude;
712	char latitude_hemisphere;
713	char longitude_hemisphere;
714	uint32_t h;
715	uint32_t m;
716	double s;
717
718	uint32_t equator = (uint32_t) ldns_power(2, 31);
719
720        if(ldns_rdf_size(rdf) < 1) {
721                return LDNS_STATUS_WIRE_RDATA_ERR;
722        }
723       	version = ldns_rdf_data(rdf)[0];
724	if (version == 0) {
725		if(ldns_rdf_size(rdf) < 16) {
726			return LDNS_STATUS_WIRE_RDATA_ERR;
727		}
728		size = ldns_rdf_data(rdf)[1];
729		horizontal_precision = ldns_rdf_data(rdf)[2];
730		vertical_precision = ldns_rdf_data(rdf)[3];
731
732		latitude = ldns_read_uint32(&ldns_rdf_data(rdf)[4]);
733		longitude = ldns_read_uint32(&ldns_rdf_data(rdf)[8]);
734		altitude = ldns_read_uint32(&ldns_rdf_data(rdf)[12]);
735
736		if (latitude > equator) {
737			latitude_hemisphere = 'N';
738			latitude = latitude - equator;
739		} else {
740			latitude_hemisphere = 'S';
741			latitude = equator - latitude;
742		}
743		h = latitude / (1000 * 60 * 60);
744		latitude = latitude % (1000 * 60 * 60);
745		m = latitude / (1000 * 60);
746		latitude = latitude % (1000 * 60);
747		s = (double) latitude / 1000.0;
748		ldns_buffer_printf(output, "%02u %02u %0.3f %c ",
749			h, m, s, latitude_hemisphere);
750
751		if (longitude > equator) {
752			longitude_hemisphere = 'E';
753			longitude = longitude - equator;
754		} else {
755			longitude_hemisphere = 'W';
756			longitude = equator - longitude;
757		}
758		h = longitude / (1000 * 60 * 60);
759		longitude = longitude % (1000 * 60 * 60);
760		m = longitude / (1000 * 60);
761		longitude = longitude % (1000 * 60);
762		s = (double) longitude / (1000.0);
763		ldns_buffer_printf(output, "%02u %02u %0.3f %c ",
764			h, m, s, longitude_hemisphere);
765
766		s = ((double) altitude) / 100;
767		s -= 100000;
768
769		if(altitude%100 != 0)
770			ldns_buffer_printf(output, "%.2f", s);
771		else
772			ldns_buffer_printf(output, "%.0f", s);
773
774		ldns_buffer_printf(output, "m ");
775
776		loc_cm_print(output, (size & 0xf0) >> 4, size & 0x0f);
777		ldns_buffer_printf(output, "m ");
778
779		loc_cm_print(output, (horizontal_precision & 0xf0) >> 4,
780			horizontal_precision & 0x0f);
781		ldns_buffer_printf(output, "m ");
782
783		loc_cm_print(output, (vertical_precision & 0xf0) >> 4,
784			vertical_precision & 0x0f);
785		ldns_buffer_printf(output, "m");
786
787		return ldns_buffer_status(output);
788	} else {
789		return ldns_rdf2buffer_str_hex(output, rdf);
790	}
791}
792
793ldns_status
794ldns_rdf2buffer_str_unknown(ldns_buffer *output, const ldns_rdf *rdf)
795{
796	ldns_buffer_printf(output, "\\# %u ", ldns_rdf_size(rdf));
797	return ldns_rdf2buffer_str_hex(output, rdf);
798}
799
800ldns_status
801ldns_rdf2buffer_str_nsap(ldns_buffer *output, const ldns_rdf *rdf)
802{
803	ldns_buffer_printf(output, "0x");
804	return ldns_rdf2buffer_str_hex(output, rdf);
805}
806
807ldns_status
808ldns_rdf2buffer_str_atma(ldns_buffer *output, const ldns_rdf *rdf)
809{
810	return ldns_rdf2buffer_str_hex(output, rdf);
811}
812
813ldns_status
814ldns_rdf2buffer_str_wks(ldns_buffer *output, const ldns_rdf *rdf)
815{
816	/* protocol, followed by bitmap of services */
817	struct protoent *protocol;
818	char *proto_name = NULL;
819	uint8_t protocol_nr;
820	struct servent *service;
821	uint16_t current_service;
822
823        if(ldns_rdf_size(rdf) < 1) {
824                return LDNS_STATUS_WIRE_RDATA_ERR;
825        }
826	protocol_nr = ldns_rdf_data(rdf)[0];
827	protocol = getprotobynumber((int) protocol_nr);
828	if (protocol && (protocol->p_name != NULL)) {
829		proto_name = protocol->p_name;
830		ldns_buffer_printf(output, "%s ", protocol->p_name);
831	} else {
832		ldns_buffer_printf(output, "%u ", protocol_nr);
833	}
834
835#ifdef HAVE_ENDPROTOENT
836	endprotoent();
837#endif
838
839	for (current_service = 0;
840	     current_service < (ldns_rdf_size(rdf)-1)*8; current_service++) {
841		if (ldns_get_bit(&(ldns_rdf_data(rdf)[1]), current_service)) {
842			service = getservbyport((int) htons(current_service),
843			                        proto_name);
844			if (service && service->s_name) {
845				ldns_buffer_printf(output, "%s ", service->s_name);
846			} else {
847				ldns_buffer_printf(output, "%u ", current_service);
848			}
849#ifdef HAVE_ENDSERVENT
850			endservent();
851#endif
852		}
853		/* exit from loop before integer overflow */
854		if(current_service == 65535) { break; }
855	}
856	return ldns_buffer_status(output);
857}
858
859static ldns_status
860ldns_rdf2buffer_str_nsec_fmt(ldns_buffer *output,
861		const ldns_output_format* fmt, const ldns_rdf *rdf)
862{
863	/* Note: this code is duplicated in higher.c in
864	 * ldns_nsec_type_check() function
865	 */
866	uint8_t window_block_nr;
867	uint8_t bitmap_length;
868	uint16_t type;
869	uint16_t pos = 0;
870	uint16_t bit_pos;
871	uint8_t *data = ldns_rdf_data(rdf);
872
873	while((size_t)(pos + 2) < ldns_rdf_size(rdf)) {
874		window_block_nr = data[pos];
875		bitmap_length = data[pos + 1];
876		pos += 2;
877		if (ldns_rdf_size(rdf) < pos + bitmap_length) {
878			return LDNS_STATUS_WIRE_RDATA_ERR;
879		}
880		for (bit_pos = 0; bit_pos < (bitmap_length) * 8; bit_pos++) {
881			if (! ldns_get_bit(&data[pos], bit_pos)) {
882				continue;
883			}
884			type = 256 * (uint16_t) window_block_nr + bit_pos;
885
886			if (! ldns_output_format_covers_type(fmt, type) &&
887					ldns_rr_descript(type) &&
888					ldns_rr_descript(type)->_name){
889
890				ldns_buffer_printf(output, "%s ",
891						ldns_rr_descript(type)->_name);
892			} else {
893				ldns_buffer_printf(output, "TYPE%u ", type);
894			}
895		}
896		pos += (uint16_t) bitmap_length;
897	}
898	return ldns_buffer_status(output);
899}
900
901ldns_status
902ldns_rdf2buffer_str_nsec(ldns_buffer *output, const ldns_rdf *rdf)
903{
904	return ldns_rdf2buffer_str_nsec_fmt(output,
905			ldns_output_format_default, rdf);
906}
907
908ldns_status
909ldns_rdf2buffer_str_nsec3_salt(ldns_buffer *output, const ldns_rdf *rdf)
910{
911	uint8_t salt_length;
912	uint8_t salt_pos;
913
914	uint8_t *data = ldns_rdf_data(rdf);
915
916        if(ldns_rdf_size(rdf) < 1) {
917                return LDNS_STATUS_WIRE_RDATA_ERR;
918        }
919	salt_length = data[0];
920	/* from now there are variable length entries so remember pos */
921	if (salt_length == 0 || ((size_t)salt_length)+1 > ldns_rdf_size(rdf)) {
922		ldns_buffer_printf(output, "- ");
923	} else {
924		for (salt_pos = 0; salt_pos < salt_length; salt_pos++) {
925			ldns_buffer_printf(output, "%02x", data[1 + salt_pos]);
926		}
927		ldns_buffer_printf(output, " ");
928	}
929
930	return ldns_buffer_status(output);
931}
932
933ldns_status
934ldns_rdf2buffer_str_period(ldns_buffer *output, const ldns_rdf *rdf)
935{
936	/* period is the number of seconds */
937	if (ldns_rdf_size(rdf) != 4) {
938		return LDNS_STATUS_WIRE_RDATA_ERR;
939	}
940	ldns_buffer_printf(output, "%u", ldns_read_uint32(ldns_rdf_data(rdf)));
941	return ldns_buffer_status(output);
942}
943
944ldns_status
945ldns_rdf2buffer_str_tsigtime(ldns_buffer *output,const  ldns_rdf *rdf)
946{
947	/* tsigtime is 48 bits network order unsigned integer */
948	uint64_t tsigtime = 0;
949	uint8_t *data = ldns_rdf_data(rdf);
950	uint64_t d0, d1, d2, d3, d4, d5;
951
952	if (ldns_rdf_size(rdf) < 6) {
953		return LDNS_STATUS_WIRE_RDATA_ERR;
954	}
955	d0 = data[0]; /* cast to uint64 for shift operations */
956	d1 = data[1];
957	d2 = data[2];
958	d3 = data[3];
959	d4 = data[4];
960	d5 = data[5];
961	tsigtime = (d0<<40) | (d1<<32) | (d2<<24) | (d3<<16) | (d4<<8) | d5;
962
963	ldns_buffer_printf(output, "%llu ", (long long)tsigtime);
964
965	return ldns_buffer_status(output);
966}
967
968ldns_status
969ldns_rdf2buffer_str_apl(ldns_buffer *output, const ldns_rdf *rdf)
970{
971	uint8_t *data = ldns_rdf_data(rdf);
972	uint16_t address_family;
973	uint8_t prefix;
974	bool negation;
975	uint8_t adf_length;
976	size_t i;
977	size_t pos = 0;
978
979	while (pos < (unsigned int) ldns_rdf_size(rdf)) {
980                if(pos + 3 >= (unsigned)ldns_rdf_size(rdf))
981                        return LDNS_STATUS_WIRE_RDATA_ERR;
982		address_family = ldns_read_uint16(&data[pos]);
983		prefix = data[pos + 2];
984		negation = data[pos + 3] & LDNS_APL_NEGATION;
985		adf_length = data[pos + 3] & LDNS_APL_MASK;
986		if (address_family == LDNS_APL_IP4) {
987			/* check if prefix < 32? */
988			if (negation) {
989				ldns_buffer_printf(output, "!");
990			}
991			ldns_buffer_printf(output, "%u:", address_family);
992			/* address is variable length 0 - 4 */
993			for (i = 0; i < 4; i++) {
994				if (i > 0) {
995					ldns_buffer_printf(output, ".");
996				}
997				if (i < (unsigned short) adf_length) {
998                                        if(pos+i+4 >= ldns_rdf_size(rdf))
999					    return LDNS_STATUS_WIRE_RDATA_ERR;
1000					ldns_buffer_printf(output, "%d",
1001					                   data[pos + i + 4]);
1002				} else {
1003					ldns_buffer_printf(output, "0");
1004				}
1005			}
1006			ldns_buffer_printf(output, "/%u ", prefix);
1007		} else if (address_family == LDNS_APL_IP6) {
1008			/* check if prefix < 128? */
1009			if (negation) {
1010				ldns_buffer_printf(output, "!");
1011			}
1012			ldns_buffer_printf(output, "%u:", address_family);
1013			/* address is variable length 0 - 16 */
1014			for (i = 0; i < 16; i++) {
1015				if (i % 2 == 0 && i > 0) {
1016					ldns_buffer_printf(output, ":");
1017				}
1018				if (i < (unsigned short) adf_length) {
1019                                        if(pos+i+4 >= ldns_rdf_size(rdf))
1020					    return LDNS_STATUS_WIRE_RDATA_ERR;
1021					ldns_buffer_printf(output, "%02x",
1022					                   data[pos + i + 4]);
1023				} else {
1024					ldns_buffer_printf(output, "00");
1025				}
1026			}
1027			ldns_buffer_printf(output, "/%u ", prefix);
1028
1029		} else {
1030			/* unknown address family */
1031			ldns_buffer_printf(output,
1032					"Unknown address family: %u data: ",
1033					address_family);
1034			for (i = 1; i < (unsigned short) (4 + adf_length); i++) {
1035                                if(pos+i >= ldns_rdf_size(rdf))
1036                                        return LDNS_STATUS_WIRE_RDATA_ERR;
1037				ldns_buffer_printf(output, "%02x", data[i]);
1038			}
1039		}
1040		pos += 4 + adf_length;
1041	}
1042	return ldns_buffer_status(output);
1043}
1044
1045ldns_status
1046ldns_rdf2buffer_str_int16_data(ldns_buffer *output, const ldns_rdf *rdf)
1047{
1048	size_t size;
1049	char *b64;
1050	if (ldns_rdf_size(rdf) < 2) {
1051		return LDNS_STATUS_WIRE_RDATA_ERR;
1052	}
1053	/* Subtract the size (2) of the number that specifies the length */
1054	size = ldns_b64_ntop_calculate_size(ldns_rdf_size(rdf) - 2);
1055	ldns_buffer_printf(output, "%u ", ldns_rdf_size(rdf) - 2);
1056	if (ldns_rdf_size(rdf) > 2) {
1057		b64 = LDNS_XMALLOC(char, size);
1058		if(!b64)
1059			return LDNS_STATUS_MEM_ERR;
1060
1061		if (ldns_rdf_size(rdf) > 2 &&
1062		ldns_b64_ntop(ldns_rdf_data(rdf) + 2,
1063					ldns_rdf_size(rdf) - 2,
1064					b64, size)) {
1065			ldns_buffer_printf(output, "%s", b64);
1066		}
1067		LDNS_FREE(b64);
1068	}
1069	return ldns_buffer_status(output);
1070}
1071
1072ldns_status
1073ldns_rdf2buffer_str_ipseckey(ldns_buffer *output, const ldns_rdf *rdf)
1074{
1075	/* wire format from
1076	   http://www.ietf.org/internet-drafts/draft-ietf-ipseckey-rr-12.txt
1077	*/
1078	uint8_t *data = ldns_rdf_data(rdf);
1079	uint8_t precedence;
1080	uint8_t gateway_type;
1081	uint8_t algorithm;
1082
1083	ldns_rdf *gateway = NULL;
1084	uint8_t *gateway_data;
1085
1086	size_t public_key_size;
1087	uint8_t *public_key_data;
1088	ldns_rdf *public_key;
1089
1090	size_t offset = 0;
1091	ldns_status status;
1092
1093	if (ldns_rdf_size(rdf) < 3) {
1094		return LDNS_STATUS_WIRE_RDATA_ERR;
1095	}
1096	precedence = data[0];
1097	gateway_type = data[1];
1098	algorithm = data[2];
1099	offset = 3;
1100
1101	switch (gateway_type) {
1102		case 0:
1103			/* no gateway */
1104			break;
1105		case 1:
1106			if (ldns_rdf_size(rdf) < offset + LDNS_IP4ADDRLEN) {
1107				return LDNS_STATUS_ERR;
1108			}
1109			gateway_data = LDNS_XMALLOC(uint8_t, LDNS_IP4ADDRLEN);
1110                        if(!gateway_data)
1111                                return LDNS_STATUS_MEM_ERR;
1112			memcpy(gateway_data, &data[offset], LDNS_IP4ADDRLEN);
1113			gateway = ldns_rdf_new(LDNS_RDF_TYPE_A,
1114					LDNS_IP4ADDRLEN , gateway_data);
1115			offset += LDNS_IP4ADDRLEN;
1116                        if(!gateway) {
1117                                LDNS_FREE(gateway_data);
1118                                return LDNS_STATUS_MEM_ERR;
1119                        }
1120			break;
1121		case 2:
1122			if (ldns_rdf_size(rdf) < offset + LDNS_IP6ADDRLEN) {
1123				return LDNS_STATUS_ERR;
1124			}
1125			gateway_data = LDNS_XMALLOC(uint8_t, LDNS_IP6ADDRLEN);
1126                        if(!gateway_data)
1127                                return LDNS_STATUS_MEM_ERR;
1128			memcpy(gateway_data, &data[offset], LDNS_IP6ADDRLEN);
1129			offset += LDNS_IP6ADDRLEN;
1130			gateway =
1131				ldns_rdf_new(LDNS_RDF_TYPE_AAAA,
1132						LDNS_IP6ADDRLEN, gateway_data);
1133                        if(!gateway) {
1134                                LDNS_FREE(gateway_data);
1135                                return LDNS_STATUS_MEM_ERR;
1136                        }
1137			break;
1138		case 3:
1139			status = ldns_wire2dname(&gateway, data,
1140					ldns_rdf_size(rdf), &offset);
1141                        if(status != LDNS_STATUS_OK)
1142                                return status;
1143			break;
1144		default:
1145			/* error? */
1146			break;
1147	}
1148
1149	if (ldns_rdf_size(rdf) <= offset) {
1150                ldns_rdf_deep_free(gateway);
1151		return LDNS_STATUS_ERR;
1152	}
1153	public_key_size = ldns_rdf_size(rdf) - offset;
1154	public_key_data = LDNS_XMALLOC(uint8_t, public_key_size);
1155        if(!public_key_data) {
1156                ldns_rdf_deep_free(gateway);
1157                return LDNS_STATUS_MEM_ERR;
1158        }
1159	memcpy(public_key_data, &data[offset], public_key_size);
1160	public_key = ldns_rdf_new(LDNS_RDF_TYPE_B64,
1161			public_key_size, public_key_data);
1162        if(!public_key) {
1163                LDNS_FREE(public_key_data);
1164                ldns_rdf_deep_free(gateway);
1165                return LDNS_STATUS_MEM_ERR;
1166        }
1167
1168	ldns_buffer_printf(output, "%u %u %u ", precedence, gateway_type, algorithm);
1169	if (gateway)
1170	  	(void) ldns_rdf2buffer_str(output, gateway);
1171	else
1172		ldns_buffer_printf(output, ".");
1173	ldns_buffer_printf(output, " ");
1174	(void) ldns_rdf2buffer_str(output, public_key);
1175
1176	ldns_rdf_deep_free(gateway);
1177	ldns_rdf_deep_free(public_key);
1178
1179	return ldns_buffer_status(output);
1180}
1181
1182ldns_status
1183ldns_rdf2buffer_str_ilnp64(ldns_buffer *output, const ldns_rdf *rdf)
1184{
1185	if (ldns_rdf_size(rdf) != 8) {
1186		return LDNS_STATUS_WIRE_RDATA_ERR;
1187	}
1188	ldns_buffer_printf(output,"%.4x:%.4x:%.4x:%.4x",
1189				ldns_read_uint16(ldns_rdf_data(rdf)),
1190				ldns_read_uint16(ldns_rdf_data(rdf)+2),
1191				ldns_read_uint16(ldns_rdf_data(rdf)+4),
1192				ldns_read_uint16(ldns_rdf_data(rdf)+6));
1193	return ldns_buffer_status(output);
1194}
1195
1196ldns_status
1197ldns_rdf2buffer_str_eui48(ldns_buffer *output, const ldns_rdf *rdf)
1198{
1199	if (ldns_rdf_size(rdf) != 6) {
1200		return LDNS_STATUS_WIRE_RDATA_ERR;
1201	}
1202	ldns_buffer_printf(output,"%.2x-%.2x-%.2x-%.2x-%.2x-%.2x",
1203				ldns_rdf_data(rdf)[0], ldns_rdf_data(rdf)[1],
1204				ldns_rdf_data(rdf)[2], ldns_rdf_data(rdf)[3],
1205				ldns_rdf_data(rdf)[4], ldns_rdf_data(rdf)[5]);
1206	return ldns_buffer_status(output);
1207}
1208
1209ldns_status
1210ldns_rdf2buffer_str_eui64(ldns_buffer *output, const ldns_rdf *rdf)
1211{
1212	if (ldns_rdf_size(rdf) != 8) {
1213		return LDNS_STATUS_WIRE_RDATA_ERR;
1214	}
1215	ldns_buffer_printf(output,"%.2x-%.2x-%.2x-%.2x-%.2x-%.2x-%.2x-%.2x",
1216				ldns_rdf_data(rdf)[0], ldns_rdf_data(rdf)[1],
1217				ldns_rdf_data(rdf)[2], ldns_rdf_data(rdf)[3],
1218				ldns_rdf_data(rdf)[4], ldns_rdf_data(rdf)[5],
1219				ldns_rdf_data(rdf)[6], ldns_rdf_data(rdf)[7]);
1220	return ldns_buffer_status(output);
1221}
1222
1223ldns_status
1224ldns_rdf2buffer_str_tag(ldns_buffer *output, const ldns_rdf *rdf)
1225{
1226	size_t nchars;
1227	const uint8_t* chars;
1228	char ch;
1229	if (ldns_rdf_size(rdf) < 2) {
1230		return LDNS_STATUS_WIRE_RDATA_ERR;
1231	}
1232	nchars = ldns_rdf_data(rdf)[0];
1233	if (nchars >= ldns_rdf_size(rdf) || /* should be rdf_size - 1 */
1234			nchars < 1) {
1235		return LDNS_STATUS_WIRE_RDATA_ERR;
1236	}
1237	chars = ldns_rdf_data(rdf) + 1;
1238	while (nchars > 0) {
1239		ch = (char)*chars++;
1240		if (! isalnum((unsigned char)ch)) {
1241			return LDNS_STATUS_WIRE_RDATA_ERR;
1242		}
1243		ldns_buffer_printf(output, "%c", ch);
1244		nchars--;
1245	}
1246	return ldns_buffer_status(output);
1247}
1248
1249ldns_status
1250ldns_rdf2buffer_str_long_str(ldns_buffer *output, const ldns_rdf *rdf)
1251{
1252
1253	ldns_buffer_printf(output, "\"");
1254	ldns_characters2buffer_str(output,
1255			ldns_rdf_size(rdf), ldns_rdf_data(rdf));
1256	ldns_buffer_printf(output, "\"");
1257	return ldns_buffer_status(output);
1258}
1259
1260ldns_status
1261ldns_rdf2buffer_str_hip(ldns_buffer *output, const ldns_rdf *rdf)
1262{
1263	uint8_t *data = ldns_rdf_data(rdf);
1264	size_t rdf_size = ldns_rdf_size(rdf);
1265	uint8_t hit_size;
1266	uint16_t pk_size;
1267	int written;
1268
1269	if (rdf_size < 6) {
1270		return LDNS_STATUS_WIRE_RDATA_ERR;
1271	}
1272	if ((hit_size = data[0]) == 0 ||
1273			(pk_size = ldns_read_uint16(data + 2)) == 0 ||
1274			rdf_size < (size_t) hit_size + pk_size + 4) {
1275
1276		return LDNS_STATUS_WIRE_RDATA_ERR;
1277	}
1278
1279	ldns_buffer_printf(output, "%d ", (int) data[1]);
1280
1281	for (data += 4; hit_size > 0; hit_size--, data++) {
1282
1283		ldns_buffer_printf(output, "%02x", (int) *data);
1284	}
1285	ldns_buffer_write_char(output, (uint8_t) ' ');
1286
1287	if (ldns_buffer_reserve(output,
1288				ldns_b64_ntop_calculate_size(pk_size))) {
1289
1290		written = ldns_b64_ntop(data, pk_size,
1291				(char *) ldns_buffer_current(output),
1292				ldns_buffer_remaining(output));
1293
1294		if (written > 0 &&
1295				written < (int) ldns_buffer_remaining(output)) {
1296
1297			output->_position += written;
1298		}
1299	}
1300	return ldns_buffer_status(output);
1301}
1302
1303/* implementation mimicked from ldns_rdf2buffer_str_ipseckey */
1304ldns_status
1305ldns_rdf2buffer_str_amtrelay(ldns_buffer *output, const ldns_rdf *rdf)
1306{
1307	/* wire format from
1308	 * draft-ietf-mboned-driad-amt-discovery Section 4.2
1309	 */
1310	uint8_t *data = ldns_rdf_data(rdf);
1311	uint8_t precedence;
1312	uint8_t discovery_optional;
1313	uint8_t relay_type;
1314
1315	ldns_rdf *relay = NULL;
1316	uint8_t *relay_data;
1317
1318	size_t offset = 0;
1319	ldns_status status;
1320
1321	if (ldns_rdf_size(rdf) < 2) {
1322		return LDNS_STATUS_WIRE_RDATA_ERR;
1323	}
1324	precedence = data[0];
1325	discovery_optional = ((data[1] & 0x80) >> 7);
1326	relay_type = data[1] & 0x7F;
1327	offset = 2;
1328
1329	switch (relay_type) {
1330		case 0:
1331			/* no relay */
1332			break;
1333		case 1:
1334			if (ldns_rdf_size(rdf) < offset + LDNS_IP4ADDRLEN) {
1335				return LDNS_STATUS_ERR;
1336			}
1337			relay_data = LDNS_XMALLOC(uint8_t, LDNS_IP4ADDRLEN);
1338                        if(!relay_data)
1339                                return LDNS_STATUS_MEM_ERR;
1340			memcpy(relay_data, &data[offset], LDNS_IP4ADDRLEN);
1341			relay = ldns_rdf_new(LDNS_RDF_TYPE_A,
1342					LDNS_IP4ADDRLEN , relay_data);
1343			offset += LDNS_IP4ADDRLEN;
1344                        if(!relay) {
1345                                LDNS_FREE(relay_data);
1346                                return LDNS_STATUS_MEM_ERR;
1347                        }
1348			break;
1349		case 2:
1350			if (ldns_rdf_size(rdf) < offset + LDNS_IP6ADDRLEN) {
1351				return LDNS_STATUS_ERR;
1352			}
1353			relay_data = LDNS_XMALLOC(uint8_t, LDNS_IP6ADDRLEN);
1354                        if(!relay_data)
1355                                return LDNS_STATUS_MEM_ERR;
1356			memcpy(relay_data, &data[offset], LDNS_IP6ADDRLEN);
1357			offset += LDNS_IP6ADDRLEN;
1358			relay =
1359				ldns_rdf_new(LDNS_RDF_TYPE_AAAA,
1360						LDNS_IP6ADDRLEN, relay_data);
1361                        if(!relay) {
1362                                LDNS_FREE(relay_data);
1363                                return LDNS_STATUS_MEM_ERR;
1364                        }
1365			break;
1366		case 3:
1367			status = ldns_wire2dname(&relay, data,
1368					ldns_rdf_size(rdf), &offset);
1369                        if(status != LDNS_STATUS_OK)
1370                                return status;
1371			break;
1372		default:
1373			/* error? */
1374			break;
1375	}
1376
1377	if (ldns_rdf_size(rdf) != offset) {
1378                ldns_rdf_deep_free(relay);
1379		return LDNS_STATUS_ERR;
1380	}
1381	ldns_buffer_printf(output, "%u %u %u ",
1382			precedence, discovery_optional, relay_type);
1383	if (relay)
1384	  	(void) ldns_rdf2buffer_str(output, relay);
1385
1386	ldns_rdf_deep_free(relay);
1387	return ldns_buffer_status(output);
1388}
1389
1390#ifdef RRTYPE_SVCB_HTTPS
1391ldns_status svcparam_key2buffer_str(ldns_buffer *output, uint16_t key);
1392
1393static ldns_status
1394svcparam_mandatory2buffer_str(ldns_buffer *output, size_t sz, uint8_t *data)
1395{
1396	if (sz % 2)
1397		return LDNS_STATUS_INVALID_SVCPARAM_VALUE;
1398
1399	svcparam_key2buffer_str(output, ldns_read_uint16(data));
1400	for (data += 2, sz -= 2; sz; data += 2, sz -= 2) {
1401		ldns_buffer_write_char(output, ',');
1402		svcparam_key2buffer_str(output, ldns_read_uint16(data));
1403	}
1404	return ldns_buffer_status(output);
1405}
1406
1407static ldns_status
1408svcparam_alpn2buffer_str(ldns_buffer *output, size_t sz, uint8_t *data)
1409{
1410	uint8_t *eod = data + sz, *dp;
1411	bool quote = false;
1412	size_t i;
1413
1414	for (dp = data; dp < eod && !quote; dp += 1 + *dp) {
1415		if (dp + 1 + *dp > eod)
1416			return LDNS_STATUS_INVALID_SVCPARAM_VALUE;
1417
1418		for (i = 0; i < *dp; i++)
1419			if (isspace(dp[i + 1]))
1420				break;
1421		quote = i < *dp;
1422	}
1423	if (quote)
1424		ldns_buffer_write_char(output, '"');
1425	while (data < eod) {
1426		uint8_t *eot = data + 1 + *data;
1427
1428		if (eot > eod)
1429			return LDNS_STATUS_INVALID_SVCPARAM_VALUE;
1430
1431		if (eod - data < (int)sz)
1432			ldns_buffer_write_char(output, ',');
1433
1434		for (data += 1; data < eot; data += 1) {
1435			uint8_t ch = *data;
1436
1437			if (isprint(ch) || ch == '\t') {
1438				if (ch == '"' ||  ch == ',' || ch == '\\')
1439					ldns_buffer_write_char(output, '\\');
1440				ldns_buffer_write_char(output, ch);
1441			} else
1442				ldns_buffer_printf(output, "\\%03u"
1443				                         , (unsigned)ch);
1444		}
1445	}
1446	if (quote)
1447		ldns_buffer_write_char(output, '"');
1448	return ldns_buffer_status(output);
1449}
1450
1451static ldns_status
1452svcparam_port2buffer_str(ldns_buffer *output, size_t sz, uint8_t *data)
1453{
1454	if (sz != 2)
1455		return LDNS_STATUS_INVALID_SVCPARAM_VALUE;
1456	ldns_buffer_printf(output, "%d", (int)ldns_read_uint16(data));
1457	return ldns_buffer_status(output);
1458}
1459
1460static ldns_status
1461svcparam_ipv4hint2buffer_str(ldns_buffer *output, size_t sz, uint8_t *data)
1462{
1463	char str[INET_ADDRSTRLEN];
1464
1465	if (sz % 4 || !inet_ntop(AF_INET, data, str, INET_ADDRSTRLEN))
1466		return LDNS_STATUS_INVALID_SVCPARAM_VALUE;
1467
1468	ldns_buffer_write_chars(output, str);
1469
1470	for (data += 4, sz -= 4; sz ; data += 4, sz -= 4 ) {
1471		ldns_buffer_write_char(output, ',');
1472		if (!inet_ntop(AF_INET, data, str, INET_ADDRSTRLEN))
1473			return LDNS_STATUS_INVALID_SVCPARAM_VALUE;
1474
1475		ldns_buffer_write_chars(output, str);
1476	}
1477	return ldns_buffer_status(output);
1478}
1479
1480static ldns_status
1481svcparam_ech2buffer_str(ldns_buffer *output, size_t sz, uint8_t *data)
1482{
1483	size_t str_sz = ldns_b64_ntop_calculate_size(sz);
1484	int written;
1485
1486	if (!ldns_buffer_reserve(output, str_sz))
1487		return LDNS_STATUS_MEM_ERR;
1488
1489	written = ldns_b64_ntop( data, sz
1490	                       , (char *)ldns_buffer_current(output), str_sz);
1491	if (written > 0)
1492		ldns_buffer_skip(output, written);
1493	else
1494		return LDNS_STATUS_INVALID_SVCPARAM_VALUE;
1495
1496	return ldns_buffer_status(output);
1497}
1498
1499static ldns_status
1500svcparam_ipv6hint2buffer_str(ldns_buffer *output, size_t sz, uint8_t *data)
1501{
1502	char str[INET6_ADDRSTRLEN];
1503
1504	if (sz % 16 || !inet_ntop(AF_INET6, data, str, INET6_ADDRSTRLEN))
1505		return LDNS_STATUS_INVALID_SVCPARAM_VALUE;
1506
1507	ldns_buffer_write_chars(output, str);
1508
1509	for (data += 16, sz -= 16; sz ; data += 16, sz -= 16) {
1510		ldns_buffer_write_char(output, ',');
1511		if (!inet_ntop(AF_INET6, data, str, INET6_ADDRSTRLEN))
1512			return LDNS_STATUS_INVALID_SVCPARAM_VALUE;
1513
1514		ldns_buffer_write_chars(output, str);
1515	}
1516	return ldns_buffer_status(output);
1517}
1518
1519static ldns_status
1520svcparam_value2buffer_str(ldns_buffer *output, size_t sz, uint8_t *data)
1521{
1522	uint8_t *eod = data + sz, *dp;
1523	bool quote = false;
1524
1525	for (dp = data; dp < eod && !isspace(*dp); dp++)
1526		; /* pass */
1527
1528	if ((quote = dp < eod))
1529		ldns_buffer_write_char(output, '"');
1530
1531	for (dp = data; dp < eod; dp++) {
1532		uint8_t ch = *dp;
1533
1534		if (isprint(ch) || ch == '\t') {
1535			if (ch == '"' ||  ch == '\\')
1536				ldns_buffer_write_char(output, '\\');
1537			ldns_buffer_write_char(output, ch);
1538		} else
1539			ldns_buffer_printf(output, "\\%03u", (unsigned)ch);
1540	}
1541	if (quote)
1542		ldns_buffer_write_char(output, '"');
1543	return ldns_buffer_status(output);
1544}
1545
1546ldns_status
1547ldns_rdf2buffer_str_svcparams(ldns_buffer *output, const ldns_rdf *rdf)
1548{
1549	uint8_t    *data, *dp, *next_dp = NULL;
1550	size_t      sz;
1551	ldns_status st;
1552
1553	if (!output)
1554		return LDNS_STATUS_NULL;
1555
1556	if (!rdf || !(data = ldns_rdf_data(rdf)) || !(sz = ldns_rdf_size(rdf)))
1557		/* No svcparams is just fine. Just nothing to print. */
1558		return LDNS_STATUS_OK;
1559
1560	for (dp = data; dp + 4 <= data + sz; dp = next_dp) {
1561		ldns_svcparam_key key    = ldns_read_uint16(dp);
1562		uint16_t          val_sz = ldns_read_uint16(dp + 2);
1563
1564		if ((next_dp = dp + 4 + val_sz) > data + sz)
1565			return LDNS_STATUS_RDATA_OVERFLOW;
1566
1567		if (dp > data)
1568			ldns_buffer_write_char(output, ' ');
1569
1570		if ((st = svcparam_key2buffer_str(output, key)))
1571			return st;
1572
1573		if (val_sz == 0)
1574			continue;
1575		dp += 4;
1576		ldns_buffer_write_char(output, '=');
1577		switch (key) {
1578		case LDNS_SVCPARAM_KEY_MANDATORY:
1579			st = svcparam_mandatory2buffer_str(output, val_sz, dp);
1580			break;
1581		case LDNS_SVCPARAM_KEY_ALPN:
1582			st = svcparam_alpn2buffer_str(output, val_sz, dp);
1583			break;
1584		case LDNS_SVCPARAM_KEY_NO_DEFAULT_ALPN:
1585			return LDNS_STATUS_NO_SVCPARAM_VALUE_EXPECTED;
1586		case LDNS_SVCPARAM_KEY_PORT:
1587			st = svcparam_port2buffer_str(output, val_sz, dp);
1588			break;
1589		case LDNS_SVCPARAM_KEY_IPV4HINT:
1590			st = svcparam_ipv4hint2buffer_str(output, val_sz, dp);
1591			break;
1592		case LDNS_SVCPARAM_KEY_ECH:
1593			st = svcparam_ech2buffer_str(output, val_sz, dp);
1594			break;
1595		case LDNS_SVCPARAM_KEY_IPV6HINT:
1596			st = svcparam_ipv6hint2buffer_str(output, val_sz, dp);
1597			break;
1598		default:
1599			st = svcparam_value2buffer_str(output, val_sz, dp);
1600			break;
1601		}
1602		if (st)
1603			return st;
1604	}
1605	return ldns_buffer_status(output);
1606}
1607#else	/* #ifdef RRTYPE_SVCB_HTTPS */
1608ldns_status
1609ldns_rdf2buffer_str_svcparams(ldns_buffer *output, const ldns_rdf *rdf)
1610{
1611	(void)output; (void)rdf;
1612	return LDNS_STATUS_NOT_IMPL;
1613}
1614#endif	/* #ifdef RRTYPE_SVCB_HTTPS */
1615
1616static ldns_status
1617ldns_rdf2buffer_str_fmt(ldns_buffer *buffer,
1618		const ldns_output_format* fmt, const ldns_rdf *rdf)
1619{
1620	ldns_status res = LDNS_STATUS_OK;
1621
1622	/*ldns_buffer_printf(buffer, "%u:", ldns_rdf_get_type(rdf));*/
1623	if (rdf) {
1624		switch(ldns_rdf_get_type(rdf)) {
1625		case LDNS_RDF_TYPE_NONE:
1626			break;
1627		case LDNS_RDF_TYPE_DNAME:
1628			res = ldns_rdf2buffer_str_dname(buffer, rdf);
1629			break;
1630		case LDNS_RDF_TYPE_INT8: /* Don't output mnemonics for these */
1631		case LDNS_RDF_TYPE_ALG:
1632		case LDNS_RDF_TYPE_CERTIFICATE_USAGE:
1633		case LDNS_RDF_TYPE_SELECTOR:
1634		case LDNS_RDF_TYPE_MATCHING_TYPE:
1635			res = ldns_rdf2buffer_str_int8(buffer, rdf);
1636			break;
1637		case LDNS_RDF_TYPE_INT16:
1638			res = ldns_rdf2buffer_str_int16(buffer, rdf);
1639			break;
1640		case LDNS_RDF_TYPE_INT32:
1641			res = ldns_rdf2buffer_str_int32(buffer, rdf);
1642			break;
1643		case LDNS_RDF_TYPE_PERIOD:
1644			res = ldns_rdf2buffer_str_period(buffer, rdf);
1645			break;
1646		case LDNS_RDF_TYPE_TSIGTIME:
1647			res = ldns_rdf2buffer_str_tsigtime(buffer, rdf);
1648			break;
1649		case LDNS_RDF_TYPE_A:
1650			res = ldns_rdf2buffer_str_a(buffer, rdf);
1651			break;
1652		case LDNS_RDF_TYPE_AAAA:
1653			res = ldns_rdf2buffer_str_aaaa(buffer, rdf);
1654			break;
1655		case LDNS_RDF_TYPE_STR:
1656			res = ldns_rdf2buffer_str_str(buffer, rdf);
1657			break;
1658		case LDNS_RDF_TYPE_APL:
1659			res = ldns_rdf2buffer_str_apl(buffer, rdf);
1660			break;
1661		case LDNS_RDF_TYPE_B32_EXT:
1662			res = ldns_rdf2buffer_str_b32_ext(buffer, rdf);
1663			break;
1664		case LDNS_RDF_TYPE_B64:
1665			res = ldns_rdf2buffer_str_b64(buffer, rdf);
1666			break;
1667		case LDNS_RDF_TYPE_HEX:
1668			res = ldns_rdf2buffer_str_hex(buffer, rdf);
1669			break;
1670		case LDNS_RDF_TYPE_NSEC:
1671			res = ldns_rdf2buffer_str_nsec_fmt(buffer, fmt, rdf);
1672			break;
1673		case LDNS_RDF_TYPE_NSEC3_SALT:
1674			res = ldns_rdf2buffer_str_nsec3_salt(buffer, rdf);
1675			break;
1676		case LDNS_RDF_TYPE_TYPE:
1677			res = ldns_rdf2buffer_str_type_fmt(buffer, fmt, rdf);
1678			break;
1679		case LDNS_RDF_TYPE_CLASS:
1680			res = ldns_rdf2buffer_str_class(buffer, rdf);
1681			break;
1682		case LDNS_RDF_TYPE_CERT_ALG:
1683			res = ldns_rdf2buffer_str_cert_alg(buffer, rdf);
1684			break;
1685		case LDNS_RDF_TYPE_UNKNOWN:
1686			res = ldns_rdf2buffer_str_unknown(buffer, rdf);
1687			break;
1688		case LDNS_RDF_TYPE_TIME:
1689			res = ldns_rdf2buffer_str_time(buffer, rdf);
1690			break;
1691		case LDNS_RDF_TYPE_HIP:
1692			res = ldns_rdf2buffer_str_hip(buffer, rdf);
1693			break;
1694		case LDNS_RDF_TYPE_LOC:
1695			res = ldns_rdf2buffer_str_loc(buffer, rdf);
1696			break;
1697		case LDNS_RDF_TYPE_WKS:
1698		case LDNS_RDF_TYPE_SERVICE:
1699			res = ldns_rdf2buffer_str_wks(buffer, rdf);
1700			break;
1701		case LDNS_RDF_TYPE_NSAP:
1702			res = ldns_rdf2buffer_str_nsap(buffer, rdf);
1703			break;
1704		case LDNS_RDF_TYPE_ATMA:
1705			res = ldns_rdf2buffer_str_atma(buffer, rdf);
1706			break;
1707		case LDNS_RDF_TYPE_IPSECKEY:
1708			res = ldns_rdf2buffer_str_ipseckey(buffer, rdf);
1709			break;
1710		case LDNS_RDF_TYPE_INT16_DATA:
1711			res = ldns_rdf2buffer_str_int16_data(buffer, rdf);
1712			break;
1713		case LDNS_RDF_TYPE_NSEC3_NEXT_OWNER:
1714			res = ldns_rdf2buffer_str_b32_ext(buffer, rdf);
1715			break;
1716		case LDNS_RDF_TYPE_ILNP64:
1717			res = ldns_rdf2buffer_str_ilnp64(buffer, rdf);
1718			break;
1719		case LDNS_RDF_TYPE_EUI48:
1720			res = ldns_rdf2buffer_str_eui48(buffer, rdf);
1721			break;
1722		case LDNS_RDF_TYPE_EUI64:
1723			res = ldns_rdf2buffer_str_eui64(buffer, rdf);
1724			break;
1725		case LDNS_RDF_TYPE_TAG:
1726			res = ldns_rdf2buffer_str_tag(buffer, rdf);
1727			break;
1728		case LDNS_RDF_TYPE_LONG_STR:
1729			res = ldns_rdf2buffer_str_long_str(buffer, rdf);
1730			break;
1731		case LDNS_RDF_TYPE_AMTRELAY:
1732			res = ldns_rdf2buffer_str_amtrelay(buffer, rdf);
1733			break;
1734		case LDNS_RDF_TYPE_SVCPARAMS:
1735			res = ldns_rdf2buffer_str_svcparams(buffer, rdf);
1736			break;
1737		}
1738	} else {
1739		/** This will write mangled RRs */
1740		ldns_buffer_printf(buffer, "(null) ");
1741		res = LDNS_STATUS_ERR;
1742	}
1743	return res;
1744}
1745
1746ldns_status
1747ldns_rdf2buffer_str(ldns_buffer *buffer, const ldns_rdf *rdf)
1748{
1749	return ldns_rdf2buffer_str_fmt(buffer,ldns_output_format_default,rdf);
1750}
1751
1752static ldns_rdf *
1753ldns_b32_ext2dname(const ldns_rdf *rdf)
1754{
1755	size_t size;
1756	char *b32;
1757	ldns_rdf *out;
1758	if(ldns_rdf_size(rdf) == 0)
1759		return NULL;
1760        /* remove -1 for the b32-hash-len octet */
1761	size = ldns_b32_ntop_calculate_size(ldns_rdf_size(rdf) - 1);
1762        /* add one for the end nul for the string */
1763	b32 = LDNS_XMALLOC(char, size + 2);
1764	if (b32) {
1765		if (ldns_b32_ntop_extended_hex(ldns_rdf_data(rdf) + 1,
1766				ldns_rdf_size(rdf) - 1, b32, size+1) > 0) {
1767			b32[size] = '.';
1768			b32[size+1] = '\0';
1769			if (ldns_str2rdf_dname(&out, b32) == LDNS_STATUS_OK) {
1770				LDNS_FREE(b32);
1771				return out;
1772			}
1773		}
1774		LDNS_FREE(b32);
1775	}
1776	return NULL;
1777}
1778
1779static ldns_status
1780ldns_rr2buffer_str_rfc3597(ldns_buffer *output, const ldns_rr *rr)
1781{
1782	size_t total_rdfsize = 0;
1783	size_t i, j;
1784
1785	ldns_buffer_printf(output, "TYPE%u\t", ldns_rr_get_type(rr));
1786	for (i = 0; i < ldns_rr_rd_count(rr); i++) {
1787		total_rdfsize += ldns_rdf_size(ldns_rr_rdf(rr, i));
1788	}
1789	if (total_rdfsize == 0) {
1790		ldns_buffer_printf(output, "\\# 0\n");
1791		return ldns_buffer_status(output);
1792	}
1793	ldns_buffer_printf(output, "\\# %d ", total_rdfsize);
1794	for (i = 0; i < ldns_rr_rd_count(rr); i++) {
1795		for (j = 0; j < ldns_rdf_size(ldns_rr_rdf(rr, i)); j++) {
1796			ldns_buffer_printf(output, "%.2x",
1797					ldns_rdf_data(ldns_rr_rdf(rr, i))[j]);
1798		}
1799	}
1800	ldns_buffer_printf(output, "\n");
1801	return ldns_buffer_status(output);
1802}
1803
1804ldns_status
1805ldns_rr2buffer_str_fmt(ldns_buffer *output,
1806		const ldns_output_format *fmt, const ldns_rr *rr)
1807{
1808	uint16_t i, flags;
1809	ldns_status status = LDNS_STATUS_OK;
1810	ldns_output_format_storage* fmt_st = (ldns_output_format_storage*)fmt;
1811
1812	if (fmt_st == NULL) {
1813		fmt_st = (ldns_output_format_storage*)
1814			  ldns_output_format_default;
1815	}
1816	if (!(fmt_st->flags & LDNS_FMT_SHORT)) {
1817		if (!rr) {
1818			if (LDNS_COMMENT_NULLS & fmt_st->flags) {
1819				ldns_buffer_printf(output, "; (null)\n");
1820			}
1821			return ldns_buffer_status(output);
1822		}
1823		if (ldns_rr_owner(rr)) {
1824			status = ldns_rdf2buffer_str_dname(output, ldns_rr_owner(rr));
1825		}
1826		if (status != LDNS_STATUS_OK) {
1827			return status;
1828		}
1829
1830		/* TTL should NOT be printed if it is a question */
1831		if (!ldns_rr_is_question(rr)) {
1832			ldns_buffer_printf(output, "\t%u", (unsigned)ldns_rr_ttl(rr));
1833		}
1834
1835		ldns_buffer_printf(output, "\t");
1836		status = ldns_rr_class2buffer_str(output, ldns_rr_get_class(rr));
1837		if (status != LDNS_STATUS_OK) {
1838			return status;
1839		}
1840		ldns_buffer_printf(output, "\t");
1841
1842		if (ldns_output_format_covers_type(fmt, ldns_rr_get_type(rr))) {
1843			return ldns_rr2buffer_str_rfc3597(output, rr);
1844		}
1845		status = ldns_rr_type2buffer_str(output, ldns_rr_get_type(rr));
1846		if (status != LDNS_STATUS_OK) {
1847			return status;
1848		}
1849
1850		if (ldns_rr_rd_count(rr) > 0) {
1851			ldns_buffer_printf(output, "\t");
1852		} else if (!ldns_rr_is_question(rr)) {
1853			ldns_buffer_printf(output, "\t\\# 0");
1854		}
1855	} else if (ldns_rr_rd_count(rr) == 0) {
1856		/* assert(fmt_st->flags & LDNS_FMT_SHORT); */
1857
1858		ldns_buffer_printf(output, "# 0");
1859	}
1860	for (i = 0; i < ldns_rr_rd_count(rr); i++) {
1861		/* ldns_rdf2buffer_str handles NULL input fine! */
1862		if ((fmt_st->flags & LDNS_FMT_ZEROIZE_RRSIGS) &&
1863				(ldns_rr_get_type(rr) == LDNS_RR_TYPE_RRSIG) &&
1864				((/* inception  */ i == 4 &&
1865				  ldns_rdf_get_type(ldns_rr_rdf(rr, 4)) ==
1866							LDNS_RDF_TYPE_TIME) ||
1867				  (/* expiration */ i == 5 &&
1868				   ldns_rdf_get_type(ldns_rr_rdf(rr, 5)) ==
1869				   			LDNS_RDF_TYPE_TIME) ||
1870				  (/* signature  */ i == 8 &&
1871				   ldns_rdf_get_type(ldns_rr_rdf(rr, 8)) ==
1872				   			LDNS_RDF_TYPE_B64))) {
1873
1874			ldns_buffer_printf(output, "(null)");
1875			status = ldns_buffer_status(output);
1876		} else if ((fmt_st->flags & LDNS_FMT_PAD_SOA_SERIAL) &&
1877				(ldns_rr_get_type(rr) == LDNS_RR_TYPE_SOA) &&
1878				/* serial */ i == 2 &&
1879			 	ldns_rdf_get_type(ldns_rr_rdf(rr, 2)) ==
1880			 				LDNS_RDF_TYPE_INT32) {
1881			ldns_buffer_printf(output, "%10lu",
1882				(unsigned long) ldns_read_uint32(
1883					ldns_rdf_data(ldns_rr_rdf(rr, 2))));
1884			status = ldns_buffer_status(output);
1885		} else {
1886			status = ldns_rdf2buffer_str_fmt(output,
1887					fmt, ldns_rr_rdf(rr, i));
1888		}
1889		if(status != LDNS_STATUS_OK)
1890			return status;
1891		if (i < ldns_rr_rd_count(rr) - 1) {
1892			ldns_buffer_printf(output, " ");
1893		}
1894	}
1895	/* per RR special comments - handy for DNSSEC types */
1896	/* check to prevent question sec. rr from
1897	 * getting here */
1898	if (ldns_rr_rd_count(rr) > 0) {
1899		switch (ldns_rr_get_type(rr)) {
1900		case LDNS_RR_TYPE_DNSKEY:
1901			/* if ldns_rr_rd_count(rr) > 0
1902				then ldns_rr_rdf(rr, 0) exists! */
1903			if (! (fmt_st->flags & LDNS_COMMENT_KEY)) {
1904				break;
1905			}
1906			flags = ldns_rdf2native_int16(ldns_rr_rdf(rr, 0));
1907			ldns_buffer_printf(output, " ;{");
1908			if (fmt_st->flags & LDNS_COMMENT_KEY_ID) {
1909				ldns_buffer_printf(output, "id = %u",
1910					(unsigned int) ldns_calc_keytag(rr));
1911			}
1912			if ((fmt_st->flags & LDNS_COMMENT_KEY_TYPE) &&
1913					(flags & LDNS_KEY_ZONE_KEY)){
1914
1915				if (flags & LDNS_KEY_SEP_KEY) {
1916					ldns_buffer_printf(output, " (ksk)");
1917				} else {
1918					ldns_buffer_printf(output, " (zsk)");
1919				}
1920				if (fmt_st->flags & LDNS_COMMENT_KEY_SIZE){
1921					ldns_buffer_printf(output, ", ");
1922				}
1923			} else if (fmt_st->flags
1924					& (LDNS_COMMENT_KEY_ID
1925						|LDNS_COMMENT_KEY_SIZE)) {
1926				ldns_buffer_printf( output, ", ");
1927			}
1928			if (fmt_st->flags & LDNS_COMMENT_KEY_SIZE) {
1929				ldns_buffer_printf(output, "size = %db",
1930					ldns_rr_dnskey_key_size(rr));
1931			}
1932			ldns_buffer_printf(output, "}");
1933			break;
1934		case LDNS_RR_TYPE_RRSIG:
1935			if ((fmt_st->flags & LDNS_COMMENT_KEY)
1936					&& (fmt_st->flags& LDNS_COMMENT_RRSIGS)
1937					&& ldns_rr_rdf(rr, 6) != NULL) {
1938				ldns_buffer_printf(output, " ;{id = %d}",
1939						ldns_rdf2native_int16(
1940							ldns_rr_rdf(rr, 6)));
1941			}
1942			break;
1943		case LDNS_RR_TYPE_DS:
1944			if ((fmt_st->flags & LDNS_COMMENT_BUBBLEBABBLE) &&
1945					ldns_rr_rdf(rr, 3) != NULL) {
1946
1947				uint8_t *data = ldns_rdf_data(
1948						ldns_rr_rdf(rr, 3));
1949				size_t len = ldns_rdf_size(ldns_rr_rdf(rr, 3));
1950				char *babble = ldns_bubblebabble(data, len);
1951				if(babble) {
1952					ldns_buffer_printf(output,
1953							" ;{%s}", babble);
1954				}
1955				LDNS_FREE(babble);
1956			}
1957			break;
1958		case LDNS_RR_TYPE_NSEC3:
1959			if (! (fmt_st->flags & LDNS_COMMENT_FLAGS) &&
1960				! (fmt_st->flags & LDNS_COMMENT_NSEC3_CHAIN)) {
1961				break;
1962			}
1963			ldns_buffer_printf(output, " ;{");
1964			if ((fmt_st->flags & LDNS_COMMENT_FLAGS)) {
1965				if (ldns_nsec3_optout(rr)) {
1966					ldns_buffer_printf(output,
1967						" flags: optout");
1968				} else {
1969					ldns_buffer_printf(output," flags: -");
1970				}
1971				if (fmt_st->flags & LDNS_COMMENT_NSEC3_CHAIN &&
1972						fmt_st->hashmap != NULL) {
1973					ldns_buffer_printf(output, ", ");
1974				}
1975			}
1976			if (fmt_st->flags & LDNS_COMMENT_NSEC3_CHAIN &&
1977					fmt_st->hashmap != NULL) {
1978				ldns_rbnode_t *node;
1979				ldns_rdf *key = ldns_dname_label(
1980						ldns_rr_owner(rr), 0);
1981				if (key) {
1982					node = ldns_rbtree_search(
1983						fmt_st->hashmap,
1984						(void *) key);
1985					if (node->data) {
1986						ldns_buffer_printf(output,
1987							"from: ");
1988						(void) ldns_rdf2buffer_str(
1989							output,
1990							ldns_dnssec_name_name(
1991							   (ldns_dnssec_name*)
1992							   node->data
1993							));
1994					}
1995					ldns_rdf_deep_free(key);
1996				}
1997				key = ldns_b32_ext2dname(
1998						ldns_nsec3_next_owner(rr));
1999				if (key) {
2000					node = ldns_rbtree_search(
2001						fmt_st->hashmap,
2002						(void *) key);
2003					if (node->data) {
2004						ldns_buffer_printf(output,
2005							" to: ");
2006						(void) ldns_rdf2buffer_str(
2007							output,
2008							ldns_dnssec_name_name(
2009							   (ldns_dnssec_name*)
2010							   node->data
2011							));
2012					}
2013					ldns_rdf_deep_free(key);
2014				}
2015			}
2016			ldns_buffer_printf(output, "}");
2017			break;
2018		default:
2019			break;
2020
2021		}
2022	}
2023	/* last */
2024	ldns_buffer_printf(output, "\n");
2025	return ldns_buffer_status(output);
2026}
2027
2028ldns_status
2029ldns_rr2buffer_str(ldns_buffer *output, const ldns_rr *rr)
2030{
2031	return ldns_rr2buffer_str_fmt(output, ldns_output_format_default, rr);
2032}
2033
2034ldns_status
2035ldns_rr_list2buffer_str_fmt(ldns_buffer *output,
2036		const ldns_output_format *fmt, const ldns_rr_list *list)
2037{
2038	uint16_t i;
2039
2040	for(i = 0; i < ldns_rr_list_rr_count(list); i++) {
2041		(void) ldns_rr2buffer_str_fmt(output, fmt,
2042				ldns_rr_list_rr(list, i));
2043	}
2044	return ldns_buffer_status(output);
2045}
2046
2047ldns_status
2048ldns_rr_list2buffer_str(ldns_buffer *output, const ldns_rr_list *list)
2049{
2050	return ldns_rr_list2buffer_str_fmt(
2051			output, ldns_output_format_default, list);
2052}
2053
2054ldns_status
2055ldns_pktheader2buffer_str(ldns_buffer *output, const ldns_pkt *pkt)
2056{
2057	ldns_lookup_table *opcode = ldns_lookup_by_id(ldns_opcodes,
2058			                    (int) ldns_pkt_get_opcode(pkt));
2059	ldns_lookup_table *rcode = ldns_lookup_by_id(ldns_rcodes,
2060			                    (int) ldns_pkt_get_rcode(pkt));
2061
2062	ldns_buffer_printf(output, ";; ->>HEADER<<- ");
2063	if (opcode) {
2064		ldns_buffer_printf(output, "opcode: %s, ", opcode->name);
2065	} else {
2066		ldns_buffer_printf(output, "opcode: ?? (%u), ",
2067				ldns_pkt_get_opcode(pkt));
2068	}
2069	if (rcode) {
2070		ldns_buffer_printf(output, "rcode: %s, ", rcode->name);
2071	} else {
2072		ldns_buffer_printf(output, "rcode: ?? (%u), ", ldns_pkt_get_rcode(pkt));
2073	}
2074	ldns_buffer_printf(output, "id: %d\n", ldns_pkt_id(pkt));
2075	ldns_buffer_printf(output, ";; flags: ");
2076
2077	if (ldns_pkt_qr(pkt)) {
2078		ldns_buffer_printf(output, "qr ");
2079	}
2080	if (ldns_pkt_aa(pkt)) {
2081		ldns_buffer_printf(output, "aa ");
2082	}
2083	if (ldns_pkt_tc(pkt)) {
2084		ldns_buffer_printf(output, "tc ");
2085	}
2086	if (ldns_pkt_rd(pkt)) {
2087		ldns_buffer_printf(output, "rd ");
2088	}
2089	if (ldns_pkt_cd(pkt)) {
2090		ldns_buffer_printf(output, "cd ");
2091	}
2092	if (ldns_pkt_ra(pkt)) {
2093		ldns_buffer_printf(output, "ra ");
2094	}
2095	if (ldns_pkt_ad(pkt)) {
2096		ldns_buffer_printf(output, "ad ");
2097	}
2098	ldns_buffer_printf(output, "; ");
2099	ldns_buffer_printf(output, "QUERY: %u, ", ldns_pkt_qdcount(pkt));
2100	ldns_buffer_printf(output, "ANSWER: %u, ", ldns_pkt_ancount(pkt));
2101	ldns_buffer_printf(output, "AUTHORITY: %u, ", ldns_pkt_nscount(pkt));
2102	ldns_buffer_printf(output, "ADDITIONAL: %u ", ldns_pkt_arcount(pkt));
2103	return ldns_buffer_status(output);
2104}
2105
2106
2107/* print EDNS option data in the Dig format: 76 61 6c 69 ... */
2108static void
2109ldns_edns_hex_data2buffer_str(ldns_buffer* output, uint8_t* data, size_t len)
2110{
2111	size_t j;
2112	for (j = 0; j < len; j++) {
2113		ldns_buffer_printf(output, " %02x", data[j]);
2114	}
2115}
2116
2117static ldns_status
2118ldns_edns_llq2buffer_str(ldns_buffer* output, uint8_t* data, size_t len)
2119{
2120	/* LLQ constants */
2121	const char* llq_errors[] = {"NO-ERROR", "SERV-FULL", "STATIC",
2122		"FORMAT-ERR", "NO-SUCH-LLQ", "BAD-VERS", "UNKNOWN_ERR"};
2123	const unsigned int llq_errors_num = 7;
2124	const char* llq_opcodes[] = {"LLQ-SETUP", "LLQ-REFRESH", "LLQ-EVENT"};
2125	const unsigned int llq_opcodes_num = 3;
2126
2127	uint16_t version, llq_opcode, error_code;
2128	uint64_t llq_id;
2129	uint32_t lease_life; /* Requested or granted life of LLQ, in seconds */
2130
2131	ldns_buffer_printf(output, "; Long-Lived Query:");
2132
2133	/* read the record */
2134	if(len != 18) {
2135		ldns_buffer_printf(output, " malformed LLQ ");
2136		ldns_edns_hex_data2buffer_str(output, data, len);
2137
2138		return ldns_buffer_status(output);
2139	}
2140	version = ldns_read_uint16(data);
2141	llq_opcode = ldns_read_uint16(data+2);
2142	error_code = ldns_read_uint16(data+4);
2143	memmove(&llq_id, data+6, sizeof(uint64_t));
2144	lease_life = ldns_read_uint32(data+14);
2145
2146	/* print option field entires */
2147	ldns_buffer_printf(output, "v%d ", (int)version);
2148
2149	if(llq_opcode < llq_opcodes_num) {
2150		ldns_buffer_printf(output, "%s", llq_opcodes[llq_opcode]);
2151	} else {
2152		ldns_buffer_printf(output, "opcode %d", (int)llq_opcode);
2153	}
2154
2155	if(error_code < llq_errors_num)
2156		ldns_buffer_printf(output, " %s", llq_errors[error_code]);
2157	else {
2158		ldns_buffer_printf(output, " error %d", (int)error_code);
2159	}
2160
2161#ifndef USE_WINSOCK
2162	ldns_buffer_printf(output, " id %llx lease-life %lu",
2163		(unsigned long long)llq_id, (unsigned long)lease_life);
2164#else
2165	ldns_buffer_printf(output, " id %I64x lease-life %lu",
2166		(unsigned long long)llq_id, (unsigned long)lease_life);
2167#endif
2168	return ldns_buffer_status(output);
2169}
2170
2171
2172static ldns_status
2173ldns_edns_ul2buffer_str(ldns_buffer* output, uint8_t* data, size_t len)
2174{
2175	uint32_t lease;
2176
2177	ldns_buffer_printf(output, "; Update Lease:");
2178
2179	if(len != 4) {
2180		ldns_buffer_printf(output, " malformed UL ");
2181		ldns_edns_hex_data2buffer_str(output, data, len);
2182		return ldns_buffer_status(output);
2183	}
2184	lease = ldns_read_uint32(data);
2185	ldns_buffer_printf(output, "lease %lu", (unsigned long)lease);
2186
2187	return ldns_buffer_status(output);
2188}
2189
2190static ldns_status
2191ldns_edns_nsid2buffer_str(ldns_buffer* output, uint8_t* data, size_t len)
2192{
2193	size_t i, printed=0;
2194
2195	ldns_buffer_printf(output, "; NSID:");
2196	ldns_edns_hex_data2buffer_str(output, data, len);
2197
2198	/* print the human-readable text string */
2199	for(i = 0; i < len; i++) {
2200		if(isprint((unsigned char)data[i]) || data[i] == '\t') {
2201			if(!printed) {
2202				ldns_buffer_printf(output, " (");
2203				printed = 1;
2204			}
2205			ldns_buffer_printf(output, "%c", (char)data[i]);
2206		}
2207	}
2208	if(printed)
2209		ldns_buffer_printf(output, ")");
2210	return ldns_buffer_status(output);
2211}
2212
2213
2214static ldns_status
2215ldns_edns_dau2buffer_str(ldns_buffer* output, uint8_t* data, size_t len)
2216{
2217	size_t i;
2218	ldns_lookup_table *lt;
2219
2220	ldns_buffer_printf(output, "; DNSSEC Algorithm Understood (DAU):");
2221
2222	for(i = 0; i <len; i++) {
2223		lt = ldns_lookup_by_id(ldns_algorithms, data[i]);
2224		if (lt && lt->name) {
2225			ldns_buffer_printf(output, " %s", lt->name);
2226		} else {
2227			ldns_buffer_printf(output, " ALG%u", data[i]);
2228		}
2229	}
2230	return ldns_buffer_status(output);
2231}
2232
2233static ldns_status
2234ldns_edns_dhu2buffer_str(ldns_buffer* output, uint8_t* data, size_t len)
2235{
2236	size_t i;
2237	ldns_lookup_table *lt;
2238
2239	ldns_buffer_printf(output, "; DS Hash Understood (DHU):");
2240
2241	for(i = 0; i < len; i++) {
2242		lt = ldns_lookup_by_id(ldns_hashes, data[i]);
2243		if (lt && lt->name) {
2244			ldns_buffer_printf(output, " %s", lt->name);
2245		} else {
2246			ldns_buffer_printf(output, " ALG%u", data[i]);
2247		}
2248	}
2249	return ldns_buffer_status(output);
2250}
2251
2252static ldns_status
2253ldns_edns_d3u2buffer_str(ldns_buffer* output, uint8_t* data, size_t len)
2254{
2255	size_t i;
2256
2257	ldns_buffer_printf(output, "; NSEC3 Hash Understood (N3U):");
2258
2259	for(i=0; i<len; i++) {
2260		if(data[i] == 1) {
2261			ldns_buffer_printf(output, " SHA1");
2262		} else {
2263			ldns_buffer_printf(output, " %d", (int)data[i]);
2264		}
2265	}
2266	return ldns_buffer_status(output);
2267}
2268
2269static ldns_status
2270ldns_edns_subnet2buffer_str(ldns_buffer* output, uint8_t* data, size_t len)
2271{
2272	uint16_t family;
2273	uint8_t source, scope;
2274	if(len < 4) {
2275		ldns_buffer_printf(output, "malformed subnet ");
2276		ldns_edns_hex_data2buffer_str(output, data, len);
2277		return ldns_buffer_status(output);
2278	}
2279	family = ldns_read_uint16(data);
2280	source = data[2];
2281	scope = data[3];
2282	if(family == 1) {
2283		/* IPv4 */
2284		char buf[64];
2285		uint8_t ip4[4];
2286		memset(ip4, 0, sizeof(ip4));
2287		if(len-4 > 4) {
2288			ldns_buffer_printf(output, "trailingdata:");
2289			ldns_edns_hex_data2buffer_str(output, data+4+4, len-4-4);
2290			ldns_buffer_printf(output, " ");
2291			len = 4+4;
2292		}
2293		memmove(ip4, data+4, len-4);
2294		if(!inet_ntop(AF_INET, ip4, buf, (socklen_t) sizeof(buf))) {
2295			ldns_buffer_printf(output, "ip4ntoperror ");
2296			ldns_edns_hex_data2buffer_str(output, data+4+4, len-4-4);
2297		} else {
2298			ldns_buffer_printf(output, "%s", buf);
2299		}
2300	} else if(family == 2) {
2301		/* IPv6 */
2302		char buf[64];
2303		uint8_t ip6[16];
2304		memset(ip6, 0, sizeof(ip6));
2305		if(len-4 > 16) {
2306			ldns_buffer_printf(output, "trailingdata:");
2307			ldns_edns_hex_data2buffer_str(output, data+4+16, len-4-16);
2308			ldns_buffer_printf(output, " ");
2309			len = 4+16;
2310		}
2311		memmove(ip6, data+4, len-4);
2312#ifdef AF_INET6
2313		if(!inet_ntop(AF_INET6, ip6, buf, (socklen_t) sizeof(buf))) {
2314			ldns_buffer_printf(output, "ip6ntoperror ");
2315			ldns_edns_hex_data2buffer_str(output, data+4+4, len-4-4);
2316		} else {
2317			ldns_buffer_printf(output, "%s", buf);
2318		}
2319#else
2320		ldns_edns_hex_data2buffer_str(output,  data+4+4, len-4-4);
2321#endif
2322	} else {
2323		/* unknown */
2324		ldns_buffer_printf(output, "family %d ", (int)family);
2325		ldns_edns_hex_data2buffer_str(output, data, len);
2326	}
2327	ldns_buffer_printf(output, "/%d scope /%d", (int)source, (int)scope);
2328
2329	return ldns_buffer_status(output);
2330}
2331
2332static ldns_status
2333ldns_edns_expire2buffer_str(ldns_buffer* output, uint8_t* data, size_t len)
2334{
2335
2336	ldns_buffer_printf(output, "; EXPIRE:");
2337
2338	if (!(len == 0) || len == 4) {
2339		ldns_buffer_printf(output, "malformed expire ");
2340		ldns_edns_hex_data2buffer_str(output, data, len);
2341
2342		return ldns_buffer_status(output);
2343	}
2344
2345	// TODO can this output be more accurate?
2346	ldns_edns_hex_data2buffer_str(output, data, len);
2347
2348	return ldns_buffer_status(output);
2349}
2350
2351
2352static ldns_status
2353ldns_edns_cookie2buffer_str(ldns_buffer* output, uint8_t* data, size_t len)
2354{
2355	ldns_buffer_printf(output, "; COOKIE:");
2356
2357	/* the size of an EDNS cookie is restricted by RFC 7873 */
2358	if (!(len == 8 || (len >= 16 && len < 40))) {
2359		ldns_buffer_printf(output, "malformed cookie ");
2360		ldns_edns_hex_data2buffer_str(output, data, len);
2361	}
2362	ldns_edns_hex_data2buffer_str(output, data, len);
2363
2364	return ldns_buffer_status(output);
2365}
2366
2367static ldns_status
2368ldns_edns_keepalive2buffer_str(ldns_buffer* output, uint8_t* data, size_t len)
2369{
2370	uint16_t timeout;
2371
2372	ldns_buffer_printf(output, "; KEEPALIVE:");
2373
2374	if(!(len == 0 || len == 2)) {
2375		ldns_buffer_printf(output, "malformed keepalive ");
2376		ldns_edns_hex_data2buffer_str(output, data, len);
2377
2378		return ldns_buffer_status(output);
2379	}
2380
2381	if(len == 0) {
2382		ldns_buffer_printf(output, "no timeout value (only valid for client option)");
2383	} else {
2384		timeout = ldns_read_uint16(data);
2385		ldns_buffer_printf(output, "timeout value in units of 100ms %u", (int)timeout);
2386	}
2387	return ldns_buffer_status(output);
2388}
2389
2390static ldns_status
2391ldns_edns_padding2buffer_str(ldns_buffer* output, uint8_t* data, size_t len)
2392{
2393	ldns_buffer_printf(output, "; PADDING: ");
2394	ldns_edns_hex_data2buffer_str(output, data, len);
2395
2396	return ldns_buffer_status(output);
2397}
2398
2399static ldns_status
2400ldns_edns_chain2buffer_str(ldns_buffer* output, uint8_t* data, size_t len)
2401{
2402	ldns_rdf** temp = NULL;
2403
2404	ldns_buffer_printf(output, "; CHAIN: ");
2405
2406	if (ldns_str2rdf_dname(temp, (char*) data) != LDNS_STATUS_OK) {
2407		ldns_buffer_printf(output, "malformed chain ");
2408		ldns_edns_hex_data2buffer_str(output, data, len);
2409
2410		return ldns_buffer_status(output);
2411	}
2412
2413	ldns_characters2buffer_str(output, len, data);
2414
2415	return ldns_buffer_status(output);
2416}
2417
2418static ldns_status
2419ldns_edns_key_tag2buffer_str(ldns_buffer* output, uint8_t* data, size_t len)
2420{
2421	size_t i;
2422
2423	ldns_buffer_printf(output, "; KEY TAG: ");
2424
2425	if(len < 2 || len % 2 != 0) {
2426		ldns_buffer_printf(output, "malformed key tag ");
2427		ldns_edns_hex_data2buffer_str(output, data, len);
2428
2429		return ldns_buffer_status(output);
2430	}
2431
2432	for (i = 0; i < len; i += 2) {
2433		uint16_t tag = ldns_read_uint16(data);
2434
2435		ldns_buffer_printf(output, " %hu", tag);
2436	}
2437
2438	return ldns_buffer_status(output);
2439}
2440
2441static ldns_status
2442ldns_edns_ede2buffer_str(ldns_buffer* output, uint8_t* data, size_t len)
2443{
2444	size_t i;
2445	uint16_t ede;
2446	ldns_buffer_printf(output, "; EDE:");
2447
2448	if(len < 2) {
2449		ldns_buffer_printf(output, "malformed ede ");
2450		ldns_edns_hex_data2buffer_str(output, data, len);
2451
2452		return ldns_buffer_status(output);
2453	}
2454
2455	ede = ldns_read_uint16(data);
2456
2457	switch (ede) {
2458	case LDNS_EDE_OTHER:
2459		ldns_buffer_printf(output, " 0 (Other): ");
2460		break;
2461	case LDNS_EDE_UNSUPPORTED_DNSKEY_ALG:
2462		ldns_buffer_printf(output, " 1 (Unsupported DNSKEY Algorithm)");
2463		break;
2464	case LDNS_EDE_UNSUPPORTED_DS_DIGEST:
2465		ldns_buffer_printf(output, " 2 (Unsupported DS Digest type)");
2466		break;
2467	case LDNS_EDE_STALE_ANSWER:
2468		ldns_buffer_printf(output, " 3 (Stale Answer)");
2469		break;
2470	case LDNS_EDE_FORGED_ANSWER:
2471		ldns_buffer_printf(output, " 4 (Forged Answer)");
2472		break;
2473	case LDNS_EDE_DNSSEC_INDETERMINATE:
2474		ldns_buffer_printf(output, " 5 (DNSSEC Indeterminate)");
2475		break;
2476	case LDNS_EDE_DNSSEC_BOGUS:
2477		ldns_buffer_printf(output, " 6 (DNSSEC Bogus)");
2478		break;
2479	case LDNS_EDE_SIGNATURE_EXPIRED:
2480		ldns_buffer_printf(output, " 7 (Signature Expired)");
2481		break;
2482	case LDNS_EDE_SIGNATURE_NOT_YET_VALID:
2483		ldns_buffer_printf(output, " 8 (Signature Not Yet Valid)");
2484		break;
2485	case LDNS_EDE_DNSKEY_MISSING:
2486		ldns_buffer_printf(output, " 9 (DNSKEY Missing)");
2487		break;
2488	case LDNS_EDE_RRSIGS_MISSING:
2489		ldns_buffer_printf(output, " 10 (RRSIGs Missing)");
2490		break;
2491	case LDNS_EDE_NO_ZONE_KEY_BIT_SET:
2492		ldns_buffer_printf(output, " 11 (No Zone Key Bit Set)");
2493		break;
2494	case LDNS_EDE_NSEC_MISSING:
2495		ldns_buffer_printf(output, " 12 (NSEC Missing)");
2496		break;
2497	case LDNS_EDE_CACHED_ERROR:
2498		ldns_buffer_printf(output, " 13 (Cached Error)");
2499		break;
2500	case LDNS_EDE_NOT_READY:
2501		ldns_buffer_printf(output, " 14 (Not Ready)");
2502		break;
2503	case LDNS_EDE_BLOCKED:
2504		ldns_buffer_printf(output, " 15 (Blocked)");
2505		break;
2506	case LDNS_EDE_CENSORED:
2507		ldns_buffer_printf(output, " 16 (Censored)");
2508		break;
2509	case LDNS_EDE_FILTERED:
2510		ldns_buffer_printf(output, " 17 (Filtered)");
2511		break;
2512	case LDNS_EDE_PROHIBITED:
2513		ldns_buffer_printf(output, " 18 (Prohibited)");
2514		break;
2515	case LDNS_EDE_STALE_NXDOMAIN_ANSWER:
2516		ldns_buffer_printf(output, " 19 (NXDOMAIN Answer)");
2517		break;
2518	case LDNS_EDE_NOT_AUTHORITATIVE:
2519		ldns_buffer_printf(output, " 20 (Not Authoritative)");
2520		break;
2521	case LDNS_EDE_NOT_SUPPORTED:
2522		ldns_buffer_printf(output, " 21 (Not Supported)");
2523		break;
2524	case LDNS_EDE_NO_REACHABLE_AUTHORITY:
2525		ldns_buffer_printf(output, " 22 (No Reachable Authority)");
2526		break;
2527	case LDNS_EDE_NETWORK_ERROR:
2528		ldns_buffer_printf(output, " 23 (Network Error)");
2529		break;
2530	case LDNS_EDE_INVALID_DATA:
2531		ldns_buffer_printf(output, " 24 (Invalid Data)");
2532		break;
2533	case LDNS_EDE_SIGNATURE_EXPIRED_BEFORE_VALID:
2534		ldns_buffer_printf(output, " 25 (Signature Expired Before Valid)");
2535		break;
2536	case LDNS_EDE_TOO_EARLY:
2537		ldns_buffer_printf(output, " 26 (Too Early)");
2538		break;
2539	default:
2540		ldns_buffer_printf(output, " %02x", data[0]);
2541		ldns_buffer_printf(output, " %02x", data[1]);
2542		break;
2543	}
2544
2545	/* skip the EDE code in the output */
2546	data += 2;
2547	len -= 2;
2548
2549	if (len > 2) {
2550		/* format the hex bytes */
2551		ldns_buffer_printf(output, ":");
2552		for (i = 0; i < len; i++) {
2553			ldns_buffer_printf(output, " %02x", data[i]);
2554		}
2555
2556		/* format the human-readable string */
2557		ldns_buffer_printf(output, " (");
2558		ldns_characters2buffer_str(output, len, data);
2559		ldns_buffer_printf(output, ")");
2560	}
2561
2562	return ldns_buffer_status(output);
2563}
2564
2565static ldns_status
2566ldns_edns_client_tag2buffer_str(ldns_buffer* output, uint8_t* data, size_t len)
2567{
2568	ldns_buffer_printf(output, "; CLIENT-TAG:");
2569
2570	if (len > 2) {
2571		ldns_buffer_printf(output, "malformed client-tag ");
2572		ldns_edns_hex_data2buffer_str(output, data, len);
2573
2574		return ldns_buffer_status(output);
2575	}
2576
2577	ldns_edns_hex_data2buffer_str(output, data, len);
2578
2579	return ldns_buffer_status(output);
2580}
2581
2582static ldns_status
2583ldns_edns_server_tag2buffer_str(ldns_buffer* output, uint8_t* data, size_t len)
2584{
2585	ldns_buffer_printf(output, "; SERVER-TAG:");
2586
2587	if (len > 2) {
2588		ldns_buffer_printf(output, "malformed server-tag ");
2589		ldns_edns_hex_data2buffer_str(output, data, len);
2590
2591		return ldns_buffer_status(output);
2592	}
2593
2594	ldns_edns_hex_data2buffer_str(output, data, len);
2595
2596	return ldns_buffer_status(output);
2597}
2598
2599ldns_status
2600ldns_edns_option_list2buffer_str(ldns_buffer *output, ldns_edns_option_list* edns_list)
2601{
2602	size_t count = ldns_edns_option_list_get_count(edns_list);
2603	size_t i, size;
2604	uint8_t* data;
2605
2606	for (i = 0; i < count; i++) {
2607		ldns_edns_option_code code;
2608		ldns_edns_option* edns = ldns_edns_option_list_get_option(edns_list, i);
2609
2610		if (!edns) {
2611			break;
2612		}
2613
2614		code = ldns_edns_get_code(edns);
2615		size = ldns_edns_get_size(edns);
2616		data = ldns_edns_get_data(edns);
2617
2618		switch(code) {
2619		case LDNS_EDNS_LLQ:
2620			ldns_edns_llq2buffer_str(output, data, size);
2621			break;
2622		case LDNS_EDNS_UL:
2623			ldns_edns_ul2buffer_str(output, data, size);
2624			break;
2625		case LDNS_EDNS_NSID:
2626			ldns_edns_nsid2buffer_str(output, data, size);
2627			break;
2628		case LDNS_EDNS_DAU:
2629			ldns_edns_dau2buffer_str(output, data, size);
2630			break;
2631		case LDNS_EDNS_DHU:
2632			ldns_edns_dhu2buffer_str(output, data, size);
2633			break;
2634		case LDNS_EDNS_N3U:
2635			ldns_edns_d3u2buffer_str(output, data, size);
2636			break;
2637		case LDNS_EDNS_CLIENT_SUBNET:
2638			ldns_edns_subnet2buffer_str(output, data, size);
2639			break;
2640		case LDNS_EDNS_EXPIRE:
2641			ldns_edns_expire2buffer_str(output, data, size);
2642			break;
2643		case LDNS_EDNS_COOKIE:
2644			ldns_edns_cookie2buffer_str(output, data, size);
2645			break;
2646		case LDNS_EDNS_KEEPALIVE:
2647			ldns_edns_keepalive2buffer_str(output, data, size);
2648			break;
2649		case LDNS_EDNS_PADDING:
2650			ldns_edns_padding2buffer_str(output, data, size);
2651			break;
2652		case LDNS_EDNS_CHAIN:
2653			ldns_edns_chain2buffer_str(output, data, size);
2654			break;
2655		case LDNS_EDNS_KEY_TAG:
2656			ldns_edns_key_tag2buffer_str(output, data, size);
2657			break;
2658		case LDNS_EDNS_EDE:
2659			ldns_edns_ede2buffer_str(output, data, size);
2660			break;
2661		case LDNS_EDNS_CLIENT_TAG:
2662			ldns_edns_client_tag2buffer_str(output, data, size);
2663			break;
2664		case LDNS_EDNS_SERVER_TAG:
2665			ldns_edns_server_tag2buffer_str(output, data, size);
2666			break;
2667		default:
2668			ldns_buffer_printf(output, "; OPT=%d:", code);
2669			ldns_edns_hex_data2buffer_str(output, data, size);
2670			break;
2671		}
2672		ldns_buffer_printf(output, "\n");
2673	}
2674
2675	return ldns_buffer_status(output);
2676}
2677
2678
2679ldns_status
2680ldns_pkt2buffer_str_fmt(ldns_buffer *output,
2681		const ldns_output_format *fmt, const ldns_pkt *pkt)
2682{
2683	uint16_t i;
2684	ldns_status status = LDNS_STATUS_OK;
2685	char *tmp;
2686	struct timeval time;
2687	time_t time_tt;
2688	int short_fmt = fmt && (fmt->flags & LDNS_FMT_SHORT);
2689
2690	if (!pkt) {
2691		ldns_buffer_printf(output, "null");
2692		return LDNS_STATUS_OK;
2693	}
2694
2695	if (!ldns_buffer_status_ok(output)) {
2696		return ldns_buffer_status(output);
2697	}
2698
2699	if (!short_fmt) {
2700		status = ldns_pktheader2buffer_str(output, pkt);
2701		if (status != LDNS_STATUS_OK) {
2702			return status;
2703		}
2704
2705		ldns_buffer_printf(output, "\n");
2706
2707		ldns_buffer_printf(output, ";; QUESTION SECTION:\n;; ");
2708
2709
2710		for (i = 0; i < ldns_pkt_qdcount(pkt); i++) {
2711			status = ldns_rr2buffer_str_fmt(output, fmt,
2712				       ldns_rr_list_rr(
2713					       ldns_pkt_question(pkt), i));
2714			if (status != LDNS_STATUS_OK) {
2715				return status;
2716			}
2717		}
2718		ldns_buffer_printf(output, "\n");
2719
2720		ldns_buffer_printf(output, ";; ANSWER SECTION:\n");
2721	}
2722	for (i = 0; i < ldns_pkt_ancount(pkt); i++) {
2723		status = ldns_rr2buffer_str_fmt(output, fmt,
2724			       ldns_rr_list_rr(
2725				       ldns_pkt_answer(pkt), i));
2726		if (status != LDNS_STATUS_OK) {
2727			return status;
2728		}
2729	}
2730	if (!short_fmt) {
2731		ldns_buffer_printf(output, "\n");
2732
2733		ldns_buffer_printf(output, ";; AUTHORITY SECTION:\n");
2734
2735		for (i = 0; i < ldns_pkt_nscount(pkt); i++) {
2736			status = ldns_rr2buffer_str_fmt(output, fmt,
2737				       ldns_rr_list_rr(
2738					       ldns_pkt_authority(pkt), i));
2739			if (status != LDNS_STATUS_OK) {
2740				return status;
2741			}
2742		}
2743		ldns_buffer_printf(output, "\n");
2744
2745		ldns_buffer_printf(output, ";; ADDITIONAL SECTION:\n");
2746		for (i = 0; i < ldns_pkt_arcount(pkt); i++) {
2747			status = ldns_rr2buffer_str_fmt(output, fmt,
2748				       ldns_rr_list_rr(
2749					       ldns_pkt_additional(pkt), i));
2750			if (status != LDNS_STATUS_OK) {
2751				return status;
2752			}
2753
2754		}
2755		ldns_buffer_printf(output, "\n");
2756		/* add some further fields */
2757		ldns_buffer_printf(output, ";; Query time: %d msec\n",
2758				ldns_pkt_querytime(pkt));
2759		if (ldns_pkt_edns(pkt)) {
2760			ldns_buffer_printf(output,
2761				   ";; EDNS: version %u; flags:",
2762				   ldns_pkt_edns_version(pkt));
2763			if (ldns_pkt_edns_do(pkt)) {
2764				ldns_buffer_printf(output, " do");
2765			}
2766			/* the extended rcode is the value set, shifted four bits,
2767			 * and or'd with the original rcode */
2768			if (ldns_pkt_edns_extended_rcode(pkt)) {
2769				ldns_buffer_printf(output, " ; ext-rcode: %d",
2770					(ldns_pkt_edns_extended_rcode(pkt) << 4 | ldns_pkt_get_rcode(pkt)));
2771			}
2772			ldns_buffer_printf(output, " ; udp: %u\n",
2773					   ldns_pkt_edns_udp_size(pkt));
2774
2775			if (pkt->_edns_list)
2776				ldns_edns_option_list2buffer_str(output, pkt->_edns_list);
2777
2778			else if (ldns_pkt_edns_data(pkt)) {
2779				ldns_edns_option_list* edns_list;
2780				/* parse the EDNS data into separate EDNS options
2781				 * and add them to the list */
2782				if ((edns_list = pkt_edns_data2edns_option_list(ldns_pkt_edns_data(pkt)))) {
2783					ldns_edns_option_list2buffer_str(output, edns_list);
2784					ldns_edns_option_list_deep_free(edns_list);
2785				} else {
2786					ldns_buffer_printf(output, ";; Data: ");
2787					(void)ldns_rdf2buffer_str(output, ldns_pkt_edns_data(pkt));
2788				}
2789			}
2790		}
2791		if (ldns_pkt_tsig(pkt)) {
2792			ldns_buffer_printf(output, ";; TSIG:\n;; ");
2793			(void) ldns_rr2buffer_str_fmt(
2794					output, fmt, ldns_pkt_tsig(pkt));
2795			ldns_buffer_printf(output, "\n");
2796		}
2797		if (ldns_pkt_answerfrom(pkt)) {
2798			tmp = ldns_rdf2str(ldns_pkt_answerfrom(pkt));
2799			ldns_buffer_printf(output, ";; SERVER: %s\n", tmp);
2800			LDNS_FREE(tmp);
2801		}
2802		time = ldns_pkt_timestamp(pkt);
2803		time_tt = (time_t)time.tv_sec;
2804		ldns_buffer_printf(output, ";; WHEN: %s",
2805				(char*)ctime(&time_tt));
2806
2807		ldns_buffer_printf(output, ";; MSG SIZE  rcvd: %d\n",
2808				(int)ldns_pkt_size(pkt));
2809	}
2810	return status;
2811}
2812
2813ldns_status
2814ldns_pkt2buffer_str(ldns_buffer *output, const ldns_pkt *pkt)
2815{
2816	return ldns_pkt2buffer_str_fmt(output, ldns_output_format_default, pkt);
2817}
2818
2819
2820#ifdef HAVE_SSL
2821static ldns_status
2822ldns_hmac_key2buffer_str(ldns_buffer *output, const ldns_key *k)
2823{
2824	ldns_status status;
2825	size_t i;
2826	ldns_rdf *b64_bignum;
2827
2828	ldns_buffer_printf(output, "Key: ");
2829
2830 	i = ldns_key_hmac_size(k);
2831	b64_bignum =  ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, ldns_key_hmac_key(k));
2832	status = ldns_rdf2buffer_str(output, b64_bignum);
2833	ldns_rdf_deep_free(b64_bignum);
2834	ldns_buffer_printf(output, "\n");
2835	return status;
2836}
2837#endif
2838
2839#if defined(HAVE_SSL) && defined(USE_GOST)
2840static ldns_status
2841ldns_gost_key2buffer_str(ldns_buffer *output, EVP_PKEY *p)
2842{
2843	unsigned char* pp = NULL;
2844	int ret;
2845	ldns_rdf *b64_bignum;
2846	ldns_status status;
2847
2848	ldns_buffer_printf(output, "GostAsn1: ");
2849
2850	ret = i2d_PrivateKey(p, &pp);
2851	b64_bignum = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, (size_t)ret, pp);
2852	status = ldns_rdf2buffer_str(output, b64_bignum);
2853
2854	ldns_rdf_deep_free(b64_bignum);
2855	OPENSSL_free(pp);
2856	ldns_buffer_printf(output, "\n");
2857	return status;
2858}
2859#endif
2860
2861#if defined(HAVE_SSL) && defined(USE_ED25519)
2862static ldns_status
2863ldns_ed25519_key2buffer_str(ldns_buffer *output, EVP_PKEY *p)
2864{
2865	unsigned char* pp = NULL;
2866	int ret;
2867	ldns_rdf *b64_bignum;
2868	ldns_status status;
2869
2870	ldns_buffer_printf(output, "PrivateKey: ");
2871
2872	ret = i2d_PrivateKey(p, &pp);
2873	/* 16 byte asn (302e020100300506032b657004220420) + 32byte key */
2874	if(ret != 16 + 32) {
2875		OPENSSL_free(pp);
2876		return LDNS_STATUS_ERR;
2877	}
2878	b64_bignum = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64,
2879		(size_t)ret-16, pp+16);
2880	status = ldns_rdf2buffer_str(output, b64_bignum);
2881
2882	ldns_rdf_deep_free(b64_bignum);
2883	OPENSSL_free(pp);
2884	ldns_buffer_printf(output, "\n");
2885	return status;
2886}
2887#endif
2888
2889#if defined(HAVE_SSL) && defined(USE_ED448)
2890static ldns_status
2891ldns_ed448_key2buffer_str(ldns_buffer *output, EVP_PKEY *p)
2892{
2893	unsigned char* pp = NULL;
2894	int ret;
2895	ldns_rdf *b64_bignum;
2896	ldns_status status;
2897
2898	ldns_buffer_printf(output, "PrivateKey: ");
2899
2900	ret = i2d_PrivateKey(p, &pp);
2901	/* some-ASN + 57byte key */
2902	if(ret != 16 + 57) {
2903		OPENSSL_free(pp);
2904		return LDNS_STATUS_ERR;
2905	}
2906	b64_bignum = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64,
2907		(size_t)ret-16, pp+16);
2908	status = ldns_rdf2buffer_str(output, b64_bignum);
2909
2910	ldns_rdf_deep_free(b64_bignum);
2911	OPENSSL_free(pp);
2912	ldns_buffer_printf(output, "\n");
2913	return status;
2914}
2915#endif
2916
2917#if defined(HAVE_SSL)
2918/** print one b64 encoded bignum to a line in the keybuffer */
2919static int
2920ldns_print_bignum_b64_line(ldns_buffer* output, const char* label, const BIGNUM* num)
2921{
2922	unsigned char  *bignumbuf = LDNS_XMALLOC(unsigned char, LDNS_MAX_KEYLEN);
2923	if(!bignumbuf) return 0;
2924
2925	ldns_buffer_printf(output, "%s: ", label);
2926	if(num) {
2927		ldns_rdf *b64_bignum = NULL;
2928		int i = BN_bn2bin(num, bignumbuf);
2929		if (i > LDNS_MAX_KEYLEN) {
2930			LDNS_FREE(bignumbuf);
2931			return 0;
2932		}
2933		b64_bignum =  ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, (size_t)i, bignumbuf);
2934		if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) {
2935			ldns_rdf_deep_free(b64_bignum);
2936			LDNS_FREE(bignumbuf);
2937			return 0;
2938		}
2939		ldns_rdf_deep_free(b64_bignum);
2940		ldns_buffer_printf(output, "\n");
2941	} else {
2942		ldns_buffer_printf(output, "(Not available)\n");
2943	}
2944	LDNS_FREE(bignumbuf);
2945	return 1;
2946}
2947#endif
2948
2949ldns_status
2950ldns_key2buffer_str(ldns_buffer *output, const ldns_key *k)
2951{
2952	ldns_status status = LDNS_STATUS_OK;
2953	unsigned char  *bignum;
2954#ifdef HAVE_SSL
2955	RSA *rsa;
2956#ifdef USE_DSA
2957	DSA *dsa;
2958#endif /* USE_DSA */
2959#endif /* HAVE_SSL */
2960
2961	if (!k) {
2962		return LDNS_STATUS_ERR;
2963	}
2964
2965	bignum = LDNS_XMALLOC(unsigned char, LDNS_MAX_KEYLEN);
2966	if (!bignum) {
2967		return LDNS_STATUS_ERR;
2968	}
2969
2970	if (ldns_buffer_status_ok(output)) {
2971#ifdef HAVE_SSL
2972		switch(ldns_key_algorithm(k)) {
2973			case LDNS_SIGN_RSASHA1:
2974			case LDNS_SIGN_RSASHA1_NSEC3:
2975			case LDNS_SIGN_RSASHA256:
2976			case LDNS_SIGN_RSASHA512:
2977			case LDNS_SIGN_RSAMD5:
2978				/* copied by looking at dnssec-keygen output */
2979				/* header */
2980				rsa = ldns_key_rsa_key(k);
2981
2982				ldns_buffer_printf(output,"Private-key-format: v1.2\n");
2983				switch(ldns_key_algorithm(k)) {
2984				case LDNS_SIGN_RSAMD5:
2985					ldns_buffer_printf(output,
2986								    "Algorithm: %u (RSA)\n",
2987								    LDNS_RSAMD5);
2988					break;
2989				case LDNS_SIGN_RSASHA1:
2990					ldns_buffer_printf(output,
2991								    "Algorithm: %u (RSASHA1)\n",
2992								    LDNS_RSASHA1);
2993					break;
2994				case LDNS_SIGN_RSASHA1_NSEC3:
2995					ldns_buffer_printf(output,
2996								    "Algorithm: %u (RSASHA1_NSEC3)\n",
2997								    LDNS_RSASHA1_NSEC3);
2998					break;
2999#ifdef USE_SHA2
3000				case LDNS_SIGN_RSASHA256:
3001					ldns_buffer_printf(output,
3002								    "Algorithm: %u (RSASHA256)\n",
3003								    LDNS_RSASHA256);
3004					break;
3005				case LDNS_SIGN_RSASHA512:
3006					ldns_buffer_printf(output,
3007								    "Algorithm: %u (RSASHA512)\n",
3008								    LDNS_RSASHA512);
3009					break;
3010#endif
3011				default:
3012#ifdef STDERR_MSGS
3013					fprintf(stderr, "Warning: unknown signature ");
3014					fprintf(stderr,
3015						   "algorithm type %u\n",
3016						   ldns_key_algorithm(k));
3017#endif
3018					ldns_buffer_printf(output,
3019								    "Algorithm: %u (Unknown)\n",
3020								    ldns_key_algorithm(k));
3021					break;
3022				}
3023
3024				/* print to buf, convert to bin, convert to b64,
3025				 * print to buf */
3026
3027#ifndef S_SPLINT_S
3028				if(1) {
3029					const BIGNUM *n=NULL, *e=NULL, *d=NULL,
3030						*p=NULL, *q=NULL, *dmp1=NULL,
3031						*dmq1=NULL, *iqmp=NULL;
3032#if OPENSSL_VERSION_NUMBER < 0x10100000 || (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER < 0x20700000)
3033					n = rsa->n;
3034					e = rsa->e;
3035					d = rsa->d;
3036					p = rsa->p;
3037					q = rsa->q;
3038					dmp1 = rsa->dmp1;
3039					dmq1 = rsa->dmq1;
3040					iqmp = rsa->iqmp;
3041#else
3042					RSA_get0_key(rsa, &n, &e, &d);
3043					RSA_get0_factors(rsa, &p, &q);
3044					RSA_get0_crt_params(rsa, &dmp1,
3045						&dmq1, &iqmp);
3046#endif
3047					if(!ldns_print_bignum_b64_line(output, "Modulus", n))
3048						goto error;
3049					if(!ldns_print_bignum_b64_line(output, "PublicExponent", e))
3050						goto error;
3051					if(!ldns_print_bignum_b64_line(output, "PrivateExponent", d))
3052						goto error;
3053					if(!ldns_print_bignum_b64_line(output, "Prime1", p))
3054						goto error;
3055					if(!ldns_print_bignum_b64_line(output, "Prime2", q))
3056						goto error;
3057					if(!ldns_print_bignum_b64_line(output, "Exponent1", dmp1))
3058						goto error;
3059					if(!ldns_print_bignum_b64_line(output, "Exponent2", dmq1))
3060						goto error;
3061					if(!ldns_print_bignum_b64_line(output, "Coefficient", iqmp))
3062						goto error;
3063				}
3064#endif /* splint */
3065
3066				RSA_free(rsa);
3067				break;
3068#ifdef USE_DSA
3069			case LDNS_SIGN_DSA:
3070			case LDNS_SIGN_DSA_NSEC3:
3071				dsa = ldns_key_dsa_key(k);
3072
3073				ldns_buffer_printf(output,"Private-key-format: v1.2\n");
3074				if (ldns_key_algorithm(k) == LDNS_SIGN_DSA) {
3075					ldns_buffer_printf(output,"Algorithm: 3 (DSA)\n");
3076				} else if (ldns_key_algorithm(k) == LDNS_SIGN_DSA_NSEC3) {
3077					ldns_buffer_printf(output,"Algorithm: 6 (DSA_NSEC3)\n");
3078				}
3079
3080				/* print to buf, convert to bin, convert to b64,
3081				 * print to buf */
3082				if(1) {
3083					const BIGNUM *p=NULL, *q=NULL, *g=NULL,
3084						*priv_key=NULL, *pub_key=NULL;
3085#if OPENSSL_VERSION_NUMBER < 0x10100000 || (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER < 0x20700000)
3086#ifndef S_SPLINT_S
3087					p = dsa->p;
3088					q = dsa->q;
3089					g = dsa->g;
3090					priv_key = dsa->priv_key;
3091					pub_key = dsa->pub_key;
3092#endif /* splint */
3093#else
3094					DSA_get0_pqg(dsa, &p, &q, &g);
3095					DSA_get0_key(dsa, &pub_key, &priv_key);
3096#endif
3097					if(!ldns_print_bignum_b64_line(output, "Prime(p)", p))
3098						goto error;
3099					if(!ldns_print_bignum_b64_line(output, "Subprime(q)", q))
3100						goto error;
3101					if(!ldns_print_bignum_b64_line(output, "Base(g)", g))
3102						goto error;
3103					if(!ldns_print_bignum_b64_line(output, "Private_value(x)", priv_key))
3104						goto error;
3105					if(!ldns_print_bignum_b64_line(output, "Public_value(y)", pub_key))
3106						goto error;
3107				}
3108				break;
3109#endif /* USE_DSA */
3110			case LDNS_SIGN_ECC_GOST:
3111				/* no format defined, use blob */
3112#if defined(HAVE_SSL) && defined(USE_GOST)
3113				ldns_buffer_printf(output, "Private-key-format: v1.2\n");
3114				ldns_buffer_printf(output, "Algorithm: %d (ECC-GOST)\n", LDNS_SIGN_ECC_GOST);
3115				status = ldns_gost_key2buffer_str(output,
3116#ifndef S_SPLINT_S
3117					k->_key.key
3118#else
3119					NULL
3120#endif
3121				);
3122#else
3123				goto error;
3124#endif /* GOST */
3125				break;
3126			case LDNS_SIGN_ECDSAP256SHA256:
3127			case LDNS_SIGN_ECDSAP384SHA384:
3128#ifdef USE_ECDSA
3129                                ldns_buffer_printf(output, "Private-key-format: v1.2\n");
3130				ldns_buffer_printf(output, "Algorithm: %d (", ldns_key_algorithm(k));
3131                                status=ldns_algorithm2buffer_str(output, (ldns_algorithm)ldns_key_algorithm(k));
3132#ifndef S_SPLINT_S
3133				ldns_buffer_printf(output, ")\n");
3134                                if(k->_key.key) {
3135                                        EC_KEY* ec = EVP_PKEY_get1_EC_KEY(k->_key.key);
3136                                        const BIGNUM* b = EC_KEY_get0_private_key(ec);
3137					if(!ldns_print_bignum_b64_line(output, "PrivateKey", b))
3138						goto error;
3139                                        /* down reference count in EC_KEY
3140                                         * its still assigned to the PKEY */
3141                                        EC_KEY_free(ec);
3142                                }
3143#endif /* splint */
3144#else
3145				goto error;
3146#endif /* ECDSA */
3147                                break;
3148#ifdef USE_ED25519
3149			case LDNS_SIGN_ED25519:
3150                                ldns_buffer_printf(output, "Private-key-format: v1.2\n");
3151				ldns_buffer_printf(output, "Algorithm: %d (", ldns_key_algorithm(k));
3152                                status=ldns_algorithm2buffer_str(output, (ldns_algorithm)ldns_key_algorithm(k));
3153				ldns_buffer_printf(output, ")\n");
3154				if (status) break;
3155				status = ldns_ed25519_key2buffer_str(output,
3156					k->_key.key);
3157				break;
3158#endif /* USE_ED25519 */
3159#ifdef USE_ED448
3160			case LDNS_SIGN_ED448:
3161                                ldns_buffer_printf(output, "Private-key-format: v1.2\n");
3162				ldns_buffer_printf(output, "Algorithm: %d (", ldns_key_algorithm(k));
3163                                status=ldns_algorithm2buffer_str(output, (ldns_algorithm)ldns_key_algorithm(k));
3164				ldns_buffer_printf(output, ")\n");
3165				if (status) break;
3166				status = ldns_ed448_key2buffer_str(output,
3167					k->_key.key);
3168				break;
3169#endif /* USE_ED448 */
3170			case LDNS_SIGN_HMACMD5:
3171				/* there's not much of a format defined for TSIG */
3172				/* It's just a binary blob, Same for all algorithms */
3173                ldns_buffer_printf(output, "Private-key-format: v1.2\n");
3174                ldns_buffer_printf(output, "Algorithm: 157 (HMAC_MD5)\n");
3175				status = ldns_hmac_key2buffer_str(output, k);
3176				break;
3177			case LDNS_SIGN_HMACSHA1:
3178		        ldns_buffer_printf(output, "Private-key-format: v1.2\n");
3179		        ldns_buffer_printf(output, "Algorithm: 158 (HMAC_SHA1)\n");
3180				status = ldns_hmac_key2buffer_str(output, k);
3181				break;
3182			case LDNS_SIGN_HMACSHA224:
3183		        ldns_buffer_printf(output, "Private-key-format: v1.2\n");
3184		        ldns_buffer_printf(output, "Algorithm: 162 (HMAC_SHA224)\n");
3185				status = ldns_hmac_key2buffer_str(output, k);
3186				break;
3187			case LDNS_SIGN_HMACSHA256:
3188		        ldns_buffer_printf(output, "Private-key-format: v1.2\n");
3189		        ldns_buffer_printf(output, "Algorithm: 159 (HMAC_SHA256)\n");
3190				status = ldns_hmac_key2buffer_str(output, k);
3191				break;
3192			case LDNS_SIGN_HMACSHA384:
3193		        ldns_buffer_printf(output, "Private-key-format: v1.2\n");
3194		        ldns_buffer_printf(output, "Algorithm: 164 (HMAC_SHA384)\n");
3195				status = ldns_hmac_key2buffer_str(output, k);
3196				break;
3197			case LDNS_SIGN_HMACSHA512:
3198		        ldns_buffer_printf(output, "Private-key-format: v1.2\n");
3199		        ldns_buffer_printf(output, "Algorithm: 165 (HMAC_SHA512)\n");
3200				status = ldns_hmac_key2buffer_str(output, k);
3201				break;
3202		}
3203#endif /* HAVE_SSL */
3204	} else {
3205		LDNS_FREE(bignum);
3206		return ldns_buffer_status(output);
3207	}
3208	LDNS_FREE(bignum);
3209	return status;
3210
3211#ifdef HAVE_SSL
3212	/* compiles warn the label isn't used */
3213error:
3214	LDNS_FREE(bignum);
3215	return LDNS_STATUS_ERR;
3216#endif /* HAVE_SSL */
3217
3218}
3219
3220/*
3221 * Zero terminate the buffer and copy data.
3222 */
3223char *
3224ldns_buffer2str(ldns_buffer *buffer)
3225{
3226	char *str;
3227
3228	/* check if buffer ends with \0, if not, and
3229	   if there is space, add it */
3230	if (*(ldns_buffer_at(buffer, ldns_buffer_position(buffer))) != 0) {
3231		if (!ldns_buffer_reserve(buffer, 1)) {
3232			return NULL;
3233		}
3234		ldns_buffer_write_char(buffer, (uint8_t) '\0');
3235		if (!ldns_buffer_set_capacity(buffer, ldns_buffer_position(buffer))) {
3236			return NULL;
3237		}
3238	}
3239
3240	str = strdup((const char *)ldns_buffer_begin(buffer));
3241        if(!str) {
3242                return NULL;
3243        }
3244	return str;
3245}
3246
3247/*
3248 * Zero terminate the buffer and export data.
3249 */
3250char *
3251ldns_buffer_export2str(ldns_buffer *buffer)
3252{
3253	/* Append '\0' as string terminator */
3254	if (! ldns_buffer_reserve(buffer, 1)) {
3255		return NULL;
3256	}
3257	ldns_buffer_write_char(buffer, 0);
3258
3259	/* reallocate memory to the size of the string and export */
3260	ldns_buffer_set_capacity(buffer, ldns_buffer_position(buffer));
3261	return ldns_buffer_export(buffer);
3262}
3263
3264char *
3265ldns_rdf2str(const ldns_rdf *rdf)
3266{
3267	char *result = NULL;
3268	ldns_buffer *tmp_buffer = ldns_buffer_new(LDNS_MAX_PACKETLEN);
3269
3270	if (!tmp_buffer) {
3271		return NULL;
3272	}
3273	if (ldns_rdf2buffer_str(tmp_buffer, rdf) == LDNS_STATUS_OK) {
3274		/* export and return string, destroy rest */
3275		result = ldns_buffer_export2str(tmp_buffer);
3276	}
3277	ldns_buffer_free(tmp_buffer);
3278	return result;
3279}
3280
3281char *
3282ldns_rr2str_fmt(const ldns_output_format *fmt, const ldns_rr *rr)
3283{
3284	char *result = NULL;
3285	ldns_buffer *tmp_buffer = ldns_buffer_new(LDNS_MAX_PACKETLEN);
3286
3287	if (!tmp_buffer) {
3288		return NULL;
3289	}
3290	if (ldns_rr2buffer_str_fmt(tmp_buffer, fmt, rr)
3291		       	== LDNS_STATUS_OK) {
3292		/* export and return string, destroy rest */
3293		result = ldns_buffer_export2str(tmp_buffer);
3294	}
3295	ldns_buffer_free(tmp_buffer);
3296	return result;
3297}
3298
3299char *
3300ldns_rr2str(const ldns_rr *rr)
3301{
3302	return ldns_rr2str_fmt(ldns_output_format_default, rr);
3303}
3304
3305char *
3306ldns_pkt2str_fmt(const ldns_output_format *fmt, const ldns_pkt *pkt)
3307{
3308	char *result = NULL;
3309	ldns_buffer *tmp_buffer = ldns_buffer_new(LDNS_MAX_PACKETLEN);
3310
3311	if (!tmp_buffer) {
3312		return NULL;
3313	}
3314	if (ldns_pkt2buffer_str_fmt(tmp_buffer, fmt, pkt)
3315		       	== LDNS_STATUS_OK) {
3316		/* export and return string, destroy rest */
3317		result = ldns_buffer_export2str(tmp_buffer);
3318	}
3319
3320	ldns_buffer_free(tmp_buffer);
3321	return result;
3322}
3323
3324char *
3325ldns_pkt2str(const ldns_pkt *pkt)
3326{
3327	return ldns_pkt2str_fmt(ldns_output_format_default, pkt);
3328}
3329
3330char *
3331ldns_key2str(const ldns_key *k)
3332{
3333	char *result = NULL;
3334	ldns_buffer *tmp_buffer = ldns_buffer_new(LDNS_MAX_PACKETLEN);
3335
3336	if (!tmp_buffer) {
3337		return NULL;
3338	}
3339	if (ldns_key2buffer_str(tmp_buffer, k) == LDNS_STATUS_OK) {
3340		/* export and return string, destroy rest */
3341		result = ldns_buffer_export2str(tmp_buffer);
3342	}
3343	ldns_buffer_free(tmp_buffer);
3344	return result;
3345}
3346
3347char *
3348ldns_rr_list2str_fmt(const ldns_output_format *fmt, const ldns_rr_list *list)
3349{
3350	char *result = NULL;
3351	ldns_buffer *tmp_buffer = ldns_buffer_new(LDNS_MAX_PACKETLEN);
3352
3353	if (!tmp_buffer) {
3354		return NULL;
3355	}
3356	if (list) {
3357		if (ldns_rr_list2buffer_str_fmt(
3358				   tmp_buffer, fmt, list)
3359			       	== LDNS_STATUS_OK) {
3360		}
3361	} else {
3362		if (fmt == NULL) {
3363			fmt = ldns_output_format_default;
3364		}
3365		if (fmt->flags & LDNS_COMMENT_NULLS) {
3366			ldns_buffer_printf(tmp_buffer, "; (null)\n");
3367		}
3368	}
3369
3370	/* export and return string, destroy rest */
3371	result = ldns_buffer_export2str(tmp_buffer);
3372	ldns_buffer_free(tmp_buffer);
3373	return result;
3374}
3375
3376char *
3377ldns_rr_list2str(const ldns_rr_list *list)
3378{
3379	return ldns_rr_list2str_fmt(ldns_output_format_default, list);
3380}
3381
3382void
3383ldns_rdf_print(FILE *output, const ldns_rdf *rdf)
3384{
3385	char *str = ldns_rdf2str(rdf);
3386	if (str) {
3387		fprintf(output, "%s", str);
3388	} else {
3389		fprintf(output, ";Unable to convert rdf to string\n");
3390	}
3391	LDNS_FREE(str);
3392}
3393
3394void
3395ldns_rr_print_fmt(FILE *output,
3396		const ldns_output_format *fmt, const ldns_rr *rr)
3397{
3398	char *str = ldns_rr2str_fmt(fmt, rr);
3399	if (str) {
3400		fprintf(output, "%s", str);
3401	} else {
3402		fprintf(output, ";Unable to convert rr to string\n");
3403	}
3404	LDNS_FREE(str);
3405}
3406
3407void
3408ldns_rr_print(FILE *output, const ldns_rr *rr)
3409{
3410	ldns_rr_print_fmt(output, ldns_output_format_default, rr);
3411}
3412
3413void
3414ldns_pkt_print_fmt(FILE *output,
3415		const ldns_output_format *fmt, const ldns_pkt *pkt)
3416{
3417	char *str = ldns_pkt2str_fmt(fmt, pkt);
3418	if (str) {
3419		fprintf(output, "%s", str);
3420	} else {
3421		fprintf(output, ";Unable to convert packet to string\n");
3422	}
3423	LDNS_FREE(str);
3424}
3425
3426void
3427ldns_pkt_print(FILE *output, const ldns_pkt *pkt)
3428{
3429	ldns_pkt_print_fmt(output, ldns_output_format_default, pkt);
3430}
3431
3432void
3433ldns_rr_list_print_fmt(FILE *output,
3434		const ldns_output_format *fmt, const ldns_rr_list *lst)
3435{
3436	size_t i;
3437	for (i = 0; i < ldns_rr_list_rr_count(lst); i++) {
3438		ldns_rr_print_fmt(output, fmt, ldns_rr_list_rr(lst, i));
3439	}
3440}
3441
3442void
3443ldns_rr_list_print(FILE *output, const ldns_rr_list *lst)
3444{
3445	ldns_rr_list_print_fmt(output, ldns_output_format_default, lst);
3446}
3447
3448void
3449ldns_resolver_print_fmt(FILE *output,
3450		const ldns_output_format *fmt, const ldns_resolver *r)
3451{
3452	uint16_t i;
3453	ldns_rdf **n;
3454	ldns_rdf **s;
3455	size_t *rtt;
3456	if (!r) {
3457		return;
3458	}
3459	n = ldns_resolver_nameservers(r);
3460	s = ldns_resolver_searchlist(r);
3461	rtt = ldns_resolver_rtt(r);
3462
3463	fprintf(output, "port: %d\n", (int)ldns_resolver_port(r));
3464	fprintf(output, "edns0 size: %d\n", (int)ldns_resolver_edns_udp_size(r));
3465	fprintf(output, "use ip6: %d\n", (int)ldns_resolver_ip6(r));
3466
3467	fprintf(output, "recursive: %d\n", ldns_resolver_recursive(r));
3468	fprintf(output, "usevc: %d\n", ldns_resolver_usevc(r));
3469	fprintf(output, "igntc: %d\n", ldns_resolver_igntc(r));
3470	fprintf(output, "fail: %d\n", ldns_resolver_fail(r));
3471	fprintf(output, "retry: %d\n", (int)ldns_resolver_retry(r));
3472	fprintf(output, "retrans: %d\n", (int)ldns_resolver_retrans(r));
3473	fprintf(output, "fallback: %d\n", ldns_resolver_fallback(r));
3474	fprintf(output, "random: %d\n", ldns_resolver_random(r));
3475	fprintf(output, "timeout: %d\n", (int)ldns_resolver_timeout(r).tv_sec);
3476	fprintf(output, "dnssec: %d\n", ldns_resolver_dnssec(r));
3477	fprintf(output, "dnssec cd: %d\n", ldns_resolver_dnssec_cd(r));
3478	fprintf(output, "trust anchors (%d listed):\n",
3479		(int)ldns_rr_list_rr_count(ldns_resolver_dnssec_anchors(r)));
3480	ldns_rr_list_print_fmt(output, fmt, ldns_resolver_dnssec_anchors(r));
3481	fprintf(output, "tsig: %s %s\n",
3482                ldns_resolver_tsig_keyname(r)?ldns_resolver_tsig_keyname(r):"-",
3483                ldns_resolver_tsig_algorithm(r)?ldns_resolver_tsig_algorithm(r):"-");
3484	fprintf(output, "debug: %d\n", ldns_resolver_debug(r));
3485
3486	fprintf(output, "default domain: ");
3487	ldns_rdf_print(output, ldns_resolver_domain(r));
3488	fprintf(output, "\n");
3489	fprintf(output, "apply default domain: %d\n", ldns_resolver_defnames(r));
3490
3491	fprintf(output, "searchlist (%d listed):\n",  (int)ldns_resolver_searchlist_count(r));
3492	for (i = 0; i < ldns_resolver_searchlist_count(r); i++) {
3493		fprintf(output, "\t");
3494		ldns_rdf_print(output, s[i]);
3495		fprintf(output, "\n");
3496	}
3497	fprintf(output, "apply search list: %d\n", ldns_resolver_dnsrch(r));
3498
3499	fprintf(output, "nameservers (%d listed):\n", (int)ldns_resolver_nameserver_count(r));
3500	for (i = 0; i < ldns_resolver_nameserver_count(r); i++) {
3501		fprintf(output, "\t");
3502		ldns_rdf_print(output, n[i]);
3503
3504		switch ((int)rtt[i]) {
3505			case LDNS_RESOLV_RTT_MIN:
3506			fprintf(output, " - reachable\n");
3507			break;
3508			case LDNS_RESOLV_RTT_INF:
3509			fprintf(output, " - unreachable\n");
3510			break;
3511		}
3512	}
3513}
3514
3515void
3516ldns_resolver_print(FILE *output, const ldns_resolver *r)
3517{
3518	ldns_resolver_print_fmt(output, ldns_output_format_default, r);
3519}
3520
3521void
3522ldns_zone_print_fmt(FILE *output,
3523		const ldns_output_format *fmt, const ldns_zone *z)
3524{
3525	if(ldns_zone_soa(z))
3526		ldns_rr_print_fmt(output, fmt, ldns_zone_soa(z));
3527	ldns_rr_list_print_fmt(output, fmt, ldns_zone_rrs(z));
3528}
3529void
3530ldns_zone_print(FILE *output, const ldns_zone *z)
3531{
3532	ldns_zone_print_fmt(output, ldns_output_format_default, z);
3533}
3534