]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/ldns/host2str.c
pmap: move the smp_targeted_tlb_shutdown pointer stuff to amd64 pmap.h
[FreeBSD/FreeBSD.git] / contrib / ldns / host2str.c
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.  */
50 ldns_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 */
72 ldns_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  */
81 ldns_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  */
96 ldns_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 */
106 ldns_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
121 ldns_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
130 const ldns_output_format   ldns_output_format_nocomments_record = { 0, NULL };
131 const ldns_output_format  *ldns_output_format_nocomments 
132                         = &ldns_output_format_nocomments_record;
133 const ldns_output_format   ldns_output_format_onlykeyids_record = {
134         LDNS_COMMENT_KEY, NULL
135 };
136 const ldns_output_format  *ldns_output_format_onlykeyids
137                         = &ldns_output_format_onlykeyids_record;
138 const ldns_output_format  *ldns_output_format_default
139                         = &ldns_output_format_onlykeyids_record;
140
141 const ldns_output_format   ldns_output_format_bubblebabble_record = { 
142         LDNS_COMMENT_KEY | LDNS_COMMENT_BUBBLEBABBLE | LDNS_COMMENT_FLAGS, NULL
143 };
144 const ldns_output_format  *ldns_output_format_bubblebabble 
145                         = &ldns_output_format_bubblebabble_record;
146
147 static bool
148 ldns_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
156 ldns_status
157 ldns_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
176 ldns_status
177 ldns_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
196 ldns_status
197 ldns_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
208 ldns_status
209 ldns_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
220 ldns_status
221 ldns_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
234 ldns_status
235 ldns_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
249 char *
250 ldns_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
269 char *
270 ldns_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
289 char *
290 ldns_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
310 char *
311 ldns_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 */
333 ldns_status
334 ldns_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
385 ldns_status
386 ldns_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
393 ldns_status
394 ldns_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
401 ldns_status
402 ldns_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
409 ldns_status
410 ldns_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
424 ldns_status
425 ldns_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
435 ldns_status
436 ldns_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
447 static void 
448 ldns_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
467 ldns_status
468 ldns_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
483 ldns_status
484 ldns_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
505 ldns_status
506 ldns_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
526 ldns_status
527 ldns_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
537 static ldns_status
538 ldns_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
554 ldns_status
555 ldns_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
561 ldns_status
562 ldns_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
576 ldns_status
577 ldns_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
590 ldns_status
591 ldns_rdf2buffer_str_alg(ldns_buffer *output, const ldns_rdf *rdf)
592 {
593         return ldns_rdf2buffer_str_int8(output, rdf);
594 }
595
596 static void
597 loc_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
613 ldns_status
614 ldns_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
646 char *
647 ldns_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
667 ldns_status
668 ldns_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
682 char *
683 ldns_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
701 ldns_status
702 ldns_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
793 ldns_status
794 ldns_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
800 ldns_status
801 ldns_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
807 ldns_status
808 ldns_rdf2buffer_str_atma(ldns_buffer *output, const ldns_rdf *rdf)
809 {
810         return ldns_rdf2buffer_str_hex(output, rdf);
811 }
812
813 ldns_status
814 ldns_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
859 static ldns_status
860 ldns_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
901 ldns_status
902 ldns_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
908 ldns_status
909 ldns_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
933 ldns_status
934 ldns_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
944 ldns_status
945 ldns_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
968 ldns_status
969 ldns_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
1045 ldns_status
1046 ldns_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
1072 ldns_status
1073 ldns_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
1182 ldns_status
1183 ldns_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
1196 ldns_status
1197 ldns_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
1209 ldns_status
1210 ldns_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
1223 ldns_status
1224 ldns_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
1249 ldns_status
1250 ldns_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
1260 ldns_status
1261 ldns_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 */
1304 ldns_status
1305 ldns_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
1391 ldns_status svcparam_key2buffer_str(ldns_buffer *output, uint16_t key);
1392
1393 static ldns_status
1394 svcparam_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
1407 static ldns_status
1408 svcparam_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
1451 static ldns_status
1452 svcparam_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
1460 static ldns_status
1461 svcparam_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
1480 static ldns_status
1481 svcparam_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
1499 static ldns_status
1500 svcparam_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
1519 static ldns_status
1520 svcparam_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
1546 ldns_status
1547 ldns_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 */
1608 ldns_status
1609 ldns_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
1616 static ldns_status
1617 ldns_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
1746 ldns_status
1747 ldns_rdf2buffer_str(ldns_buffer *buffer, const ldns_rdf *rdf)
1748 {
1749         return ldns_rdf2buffer_str_fmt(buffer,ldns_output_format_default,rdf);
1750 }
1751
1752 static ldns_rdf *
1753 ldns_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
1779 static ldns_status
1780 ldns_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
1804 ldns_status
1805 ldns_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
2028 ldns_status
2029 ldns_rr2buffer_str(ldns_buffer *output, const ldns_rr *rr)
2030 {
2031         return ldns_rr2buffer_str_fmt(output, ldns_output_format_default, rr);
2032 }
2033
2034 ldns_status
2035 ldns_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
2047 ldns_status
2048 ldns_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
2054 ldns_status
2055 ldns_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 ... */
2108 static void
2109 ldns_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
2117 static ldns_status
2118 ldns_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
2172 static ldns_status
2173 ldns_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
2190 static ldns_status
2191 ldns_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
2214 static ldns_status
2215 ldns_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
2233 static ldns_status
2234 ldns_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
2252 static ldns_status
2253 ldns_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
2269 static ldns_status
2270 ldns_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
2332 static ldns_status
2333 ldns_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
2352 static ldns_status
2353 ldns_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
2367 static ldns_status
2368 ldns_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
2390 static ldns_status
2391 ldns_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
2399 static ldns_status
2400 ldns_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
2418 static ldns_status
2419 ldns_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
2441 static ldns_status
2442 ldns_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
2565 static ldns_status
2566 ldns_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
2582 static ldns_status
2583 ldns_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
2599 ldns_status
2600 ldns_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
2679 ldns_status
2680 ldns_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
2813 ldns_status
2814 ldns_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
2821 static ldns_status
2822 ldns_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)
2840 static ldns_status
2841 ldns_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)
2862 static ldns_status
2863 ldns_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)
2890 static ldns_status
2891 ldns_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 */
2919 static int
2920 ldns_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
2949 ldns_status
2950 ldns_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 */
3213 error:
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  */
3223 char *
3224 ldns_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  */
3250 char *
3251 ldns_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
3264 char *
3265 ldns_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
3281 char *
3282 ldns_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
3299 char *
3300 ldns_rr2str(const ldns_rr *rr)
3301 {
3302         return ldns_rr2str_fmt(ldns_output_format_default, rr);
3303 }
3304
3305 char *
3306 ldns_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
3324 char *
3325 ldns_pkt2str(const ldns_pkt *pkt)
3326 {
3327         return ldns_pkt2str_fmt(ldns_output_format_default, pkt);
3328 }
3329
3330 char *
3331 ldns_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
3347 char *
3348 ldns_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
3376 char *
3377 ldns_rr_list2str(const ldns_rr_list *list)
3378 {
3379         return ldns_rr_list2str_fmt(ldns_output_format_default, list);
3380 }
3381
3382 void
3383 ldns_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
3394 void
3395 ldns_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
3407 void
3408 ldns_rr_print(FILE *output, const ldns_rr *rr)
3409 {
3410         ldns_rr_print_fmt(output, ldns_output_format_default, rr);
3411 }
3412
3413 void
3414 ldns_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
3426 void
3427 ldns_pkt_print(FILE *output, const ldns_pkt *pkt)
3428 {
3429         ldns_pkt_print_fmt(output, ldns_output_format_default, pkt);
3430 }
3431
3432 void
3433 ldns_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
3442 void
3443 ldns_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
3448 void
3449 ldns_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
3515 void
3516 ldns_resolver_print(FILE *output, const ldns_resolver *r)
3517 {
3518         ldns_resolver_print_fmt(output, ldns_output_format_default, r);
3519 }
3520
3521 void
3522 ldns_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 }
3529 void
3530 ldns_zone_print(FILE *output, const ldns_zone *z)
3531 {
3532         ldns_zone_print_fmt(output, ldns_output_format_default, z);
3533 }