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