]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/unbound/sldns/wire2str.c
Upgrade Unbound to 1.6.6. More to follow.
[FreeBSD/FreeBSD.git] / contrib / unbound / sldns / wire2str.c
1 /*
2  * wire2str.c
3  *
4  * conversion routines from the wire format
5  * to the presentation format (strings)
6  *
7  * (c) NLnet Labs, 2004-2006
8  *
9  * See the file LICENSE for the license
10  */
11 /**
12  * \file
13  *
14  * Contains functions to translate the wireformat to text
15  * representation, as well as functions to print them.
16  */
17 #include "config.h"
18 #include "sldns/wire2str.h"
19 #include "sldns/str2wire.h"
20 #include "sldns/rrdef.h"
21 #include "sldns/pkthdr.h"
22 #include "sldns/parseutil.h"
23 #include "sldns/sbuffer.h"
24 #include "sldns/keyraw.h"
25 #ifdef HAVE_TIME_H
26 #include <time.h>
27 #endif
28 #include <sys/time.h>
29 #include <stdarg.h>
30 #include <ctype.h>
31 #ifdef HAVE_NETDB_H
32 #include <netdb.h>
33 #endif
34
35 /* lookup tables for standard DNS stuff  */
36 /* Taken from RFC 2535, section 7.  */
37 static sldns_lookup_table sldns_algorithms_data[] = {
38         { LDNS_RSAMD5, "RSAMD5" },
39         { LDNS_DH, "DH" },
40         { LDNS_DSA, "DSA" },
41         { LDNS_ECC, "ECC" },
42         { LDNS_RSASHA1, "RSASHA1" },
43         { LDNS_DSA_NSEC3, "DSA-NSEC3-SHA1" },
44         { LDNS_RSASHA1_NSEC3, "RSASHA1-NSEC3-SHA1" },
45         { LDNS_RSASHA256, "RSASHA256"},
46         { LDNS_RSASHA512, "RSASHA512"},
47         { LDNS_ECC_GOST, "ECC-GOST"},
48         { LDNS_ECDSAP256SHA256, "ECDSAP256SHA256"},
49         { LDNS_ECDSAP384SHA384, "ECDSAP384SHA384"},
50         { LDNS_ED25519, "ED25519"},
51         { LDNS_ED448, "ED448"},
52         { LDNS_INDIRECT, "INDIRECT" },
53         { LDNS_PRIVATEDNS, "PRIVATEDNS" },
54         { LDNS_PRIVATEOID, "PRIVATEOID" },
55         { 0, NULL }
56 };
57 sldns_lookup_table* sldns_algorithms = sldns_algorithms_data;
58
59 /* hash algorithms in DS record */
60 static sldns_lookup_table sldns_hashes_data[] = {
61         { LDNS_SHA1, "SHA1" },
62         { LDNS_SHA256, "SHA256" },
63         { LDNS_HASH_GOST, "HASH-GOST" },
64         { LDNS_SHA384, "SHA384" },
65         { 0, NULL }
66 };
67 sldns_lookup_table* sldns_hashes = sldns_hashes_data;
68
69 /* Taken from RFC 4398  */
70 static sldns_lookup_table sldns_cert_algorithms_data[] = {
71         { LDNS_CERT_PKIX, "PKIX" },
72         { LDNS_CERT_SPKI, "SPKI" },
73         { LDNS_CERT_PGP, "PGP" },
74         { LDNS_CERT_IPKIX, "IPKIX" },
75         { LDNS_CERT_ISPKI, "ISPKI" },
76         { LDNS_CERT_IPGP, "IPGP" },
77         { LDNS_CERT_ACPKIX, "ACPKIX" },
78         { LDNS_CERT_IACPKIX, "IACPKIX" },
79         { LDNS_CERT_URI, "URI" },
80         { LDNS_CERT_OID, "OID" },
81         { 0, NULL }
82 };
83 sldns_lookup_table* sldns_cert_algorithms = sldns_cert_algorithms_data;
84
85 /* if these are used elsewhere */
86 static sldns_lookup_table sldns_rcodes_data[] = {
87         { LDNS_RCODE_NOERROR, "NOERROR" },
88         { LDNS_RCODE_FORMERR, "FORMERR" },
89         { LDNS_RCODE_SERVFAIL, "SERVFAIL" },
90         { LDNS_RCODE_NXDOMAIN, "NXDOMAIN" },
91         { LDNS_RCODE_NOTIMPL, "NOTIMPL" },
92         { LDNS_RCODE_REFUSED, "REFUSED" },
93         { LDNS_RCODE_YXDOMAIN, "YXDOMAIN" },
94         { LDNS_RCODE_YXRRSET, "YXRRSET" },
95         { LDNS_RCODE_NXRRSET, "NXRRSET" },
96         { LDNS_RCODE_NOTAUTH, "NOTAUTH" },
97         { LDNS_RCODE_NOTZONE, "NOTZONE" },
98         { 0, NULL }
99 };
100 sldns_lookup_table* sldns_rcodes = sldns_rcodes_data;
101
102 static sldns_lookup_table sldns_opcodes_data[] = {
103         { LDNS_PACKET_QUERY, "QUERY" },
104         { LDNS_PACKET_IQUERY, "IQUERY" },
105         { LDNS_PACKET_STATUS, "STATUS" },
106         { LDNS_PACKET_NOTIFY, "NOTIFY" },
107         { LDNS_PACKET_UPDATE, "UPDATE" },
108         { 0, NULL }
109 };
110 sldns_lookup_table* sldns_opcodes = sldns_opcodes_data;
111
112 static sldns_lookup_table sldns_wireparse_errors_data[] = {
113         { LDNS_WIREPARSE_ERR_OK, "no parse error" },
114         { LDNS_WIREPARSE_ERR_GENERAL, "parse error" },
115         { LDNS_WIREPARSE_ERR_DOMAINNAME_OVERFLOW, "Domainname length overflow" },
116         { LDNS_WIREPARSE_ERR_DOMAINNAME_UNDERFLOW, "Domainname length underflow (zero length)" },
117         { LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, "buffer too small" },
118         { LDNS_WIREPARSE_ERR_LABEL_OVERFLOW, "Label length overflow" },
119         { LDNS_WIREPARSE_ERR_EMPTY_LABEL, "Empty label" },
120         { LDNS_WIREPARSE_ERR_SYNTAX_BAD_ESCAPE, "Syntax error, bad escape sequence" },
121         { LDNS_WIREPARSE_ERR_SYNTAX, "Syntax error, could not parse the RR" },
122         { LDNS_WIREPARSE_ERR_SYNTAX_TTL, "Syntax error, could not parse the RR's TTL" },
123         { LDNS_WIREPARSE_ERR_SYNTAX_TYPE, "Syntax error, could not parse the RR's type" },
124         { LDNS_WIREPARSE_ERR_SYNTAX_CLASS, "Syntax error, could not parse the RR's class" },
125         { LDNS_WIREPARSE_ERR_SYNTAX_RDATA, "Syntax error, could not parse the RR's rdata" },
126         { LDNS_WIREPARSE_ERR_SYNTAX_MISSING_VALUE, "Syntax error, value expected" },
127         { LDNS_WIREPARSE_ERR_INVALID_STR, "Conversion error, string expected" },
128         { LDNS_WIREPARSE_ERR_SYNTAX_B64, "Conversion error, b64 encoding expected" },
129         { LDNS_WIREPARSE_ERR_SYNTAX_B32_EXT, "Conversion error, b32 ext encoding expected" },
130         { LDNS_WIREPARSE_ERR_SYNTAX_HEX, "Conversion error, hex encoding expected" },
131         { LDNS_WIREPARSE_ERR_CERT_BAD_ALGORITHM, "Bad algorithm type for CERT record" },
132         { LDNS_WIREPARSE_ERR_SYNTAX_TIME, "Conversion error, time encoding expected" },
133         { LDNS_WIREPARSE_ERR_SYNTAX_PERIOD, "Conversion error, time period encoding expected" },
134         { LDNS_WIREPARSE_ERR_SYNTAX_ILNP64, "Conversion error, 4 colon separated hex numbers expected" },
135         { LDNS_WIREPARSE_ERR_SYNTAX_EUI48,
136                 "Conversion error, 6 two character hex numbers "
137                 "separated by dashes expected (i.e. xx-xx-xx-xx-xx-xx" },
138         { LDNS_WIREPARSE_ERR_SYNTAX_EUI64,
139                 "Conversion error, 8 two character hex numbers "
140                 "separated by dashes expected (i.e. xx-xx-xx-xx-xx-xx-xx-xx" },
141         { LDNS_WIREPARSE_ERR_SYNTAX_TAG,
142                 "Conversion error, a non-zero sequence of US-ASCII letters "
143                 "and numbers in lower case expected" },
144         { LDNS_WIREPARSE_ERR_NOT_IMPL, "not implemented" },
145         { LDNS_WIREPARSE_ERR_SYNTAX_INT, "Conversion error, integer expected" },
146         { LDNS_WIREPARSE_ERR_SYNTAX_IP4, "Conversion error, ip4 addr expected" },
147         { LDNS_WIREPARSE_ERR_SYNTAX_IP6, "Conversion error, ip6 addr expected" },
148         { LDNS_WIREPARSE_ERR_SYNTAX_INTEGER_OVERFLOW, "Syntax error, integer overflow" },
149         { LDNS_WIREPARSE_ERR_INCLUDE, "$INCLUDE directive was seen in the zone" },
150         { LDNS_WIREPARSE_ERR_PARENTHESIS, "Parse error, parenthesis mismatch" },
151         { 0, NULL }
152 };
153 sldns_lookup_table* sldns_wireparse_errors = sldns_wireparse_errors_data;
154
155 static sldns_lookup_table sldns_edns_flags_data[] = {
156         { 3600, "do"},
157         { 0, NULL}
158 };
159 sldns_lookup_table* sldns_edns_flags = sldns_edns_flags_data;
160
161 static sldns_lookup_table sldns_edns_options_data[] = {
162         { 1, "LLQ" },
163         { 2, "UL" },
164         { 3, "NSID" },
165         /* 4 draft-cheshire-edns0-owner-option */
166         { 5, "DAU" },
167         { 6, "DHU" },
168         { 7, "N3U" },
169         { 8, "edns-client-subnet" },
170         { 11, "edns-tcp-keepalive"},
171         { 12, "Padding" },
172         { 0, NULL}
173 };
174 sldns_lookup_table* sldns_edns_options = sldns_edns_options_data;
175
176 static sldns_lookup_table sldns_tsig_errors_data[] = {
177         { LDNS_TSIG_ERROR_NOERROR, "NOERROR" },
178         { LDNS_RCODE_FORMERR, "FORMERR" },
179         { LDNS_RCODE_SERVFAIL, "SERVFAIL" },
180         { LDNS_RCODE_NXDOMAIN, "NXDOMAIN" },
181         { LDNS_RCODE_NOTIMPL, "NOTIMPL" },
182         { LDNS_RCODE_REFUSED, "REFUSED" },
183         { LDNS_RCODE_YXDOMAIN, "YXDOMAIN" },
184         { LDNS_RCODE_YXRRSET, "YXRRSET" },
185         { LDNS_RCODE_NXRRSET, "NXRRSET" },
186         { LDNS_RCODE_NOTAUTH, "NOTAUTH" },
187         { LDNS_RCODE_NOTZONE, "NOTZONE" },
188         { LDNS_TSIG_ERROR_BADSIG, "BADSIG" },
189         { LDNS_TSIG_ERROR_BADKEY, "BADKEY" },
190         { LDNS_TSIG_ERROR_BADTIME, "BADTIME" },
191         { LDNS_TSIG_ERROR_BADMODE, "BADMODE" },
192         { LDNS_TSIG_ERROR_BADNAME, "BADNAME" },
193         { LDNS_TSIG_ERROR_BADALG, "BADALG" },
194         { 0, NULL }
195 };
196 sldns_lookup_table* sldns_tsig_errors = sldns_tsig_errors_data;
197
198 char* sldns_wire2str_pkt(uint8_t* data, size_t len)
199 {
200         size_t slen = (size_t)sldns_wire2str_pkt_buf(data, len, NULL, 0);
201         char* result = (char*)malloc(slen+1);
202         if(!result) return NULL;
203         sldns_wire2str_pkt_buf(data, len, result, slen+1);
204         return result;
205 }
206
207 char* sldns_wire2str_rr(uint8_t* rr, size_t len)
208 {
209         size_t slen = (size_t)sldns_wire2str_rr_buf(rr, len, NULL, 0);
210         char* result = (char*)malloc(slen+1);
211         if(!result) return NULL;
212         sldns_wire2str_rr_buf(rr, len, result, slen+1);
213         return result;
214 }
215
216 char* sldns_wire2str_type(uint16_t rrtype)
217 {
218         char buf[16];
219         sldns_wire2str_type_buf(rrtype, buf, sizeof(buf));
220         return strdup(buf);
221 }
222
223 char* sldns_wire2str_class(uint16_t rrclass)
224 {
225         char buf[16];
226         sldns_wire2str_class_buf(rrclass, buf, sizeof(buf));
227         return strdup(buf);
228 }
229
230 char* sldns_wire2str_dname(uint8_t* dname, size_t dname_len)
231 {
232         size_t slen=(size_t)sldns_wire2str_dname_buf(dname, dname_len, NULL, 0);
233         char* result = (char*)malloc(slen+1);
234         if(!result) return NULL;
235         sldns_wire2str_dname_buf(dname, dname_len, result, slen+1);
236         return result;
237 }
238
239 char* sldns_wire2str_rcode(int rcode)
240 {
241         char buf[16];
242         sldns_wire2str_rcode_buf(rcode, buf, sizeof(buf));
243         return strdup(buf);
244 }
245
246 int sldns_wire2str_pkt_buf(uint8_t* d, size_t dlen, char* s, size_t slen)
247 {
248         /* use arguments as temporary variables */
249         return sldns_wire2str_pkt_scan(&d, &dlen, &s, &slen);
250 }
251
252 int sldns_wire2str_rr_buf(uint8_t* d, size_t dlen, char* s, size_t slen)
253 {
254         /* use arguments as temporary variables */
255         return sldns_wire2str_rr_scan(&d, &dlen, &s, &slen, NULL, 0);
256 }
257
258 int sldns_wire2str_rdata_buf(uint8_t* rdata, size_t rdata_len, char* str,
259         size_t str_len, uint16_t rrtype)
260 {
261         /* use arguments as temporary variables */
262         return sldns_wire2str_rdata_scan(&rdata, &rdata_len, &str, &str_len,
263                 rrtype, NULL, 0);
264 }
265
266 int sldns_wire2str_rr_unknown_buf(uint8_t* d, size_t dlen, char* s, size_t slen)
267 {
268         /* use arguments as temporary variables */
269         return sldns_wire2str_rr_unknown_scan(&d, &dlen, &s, &slen, NULL, 0);
270 }
271
272 int sldns_wire2str_rr_comment_buf(uint8_t* rr, size_t rrlen, size_t dname_len,
273         char* s, size_t slen)
274 {
275         uint16_t rrtype = sldns_wirerr_get_type(rr, rrlen, dname_len);
276         return sldns_wire2str_rr_comment_print(&s, &slen, rr, rrlen, dname_len,
277                 rrtype);
278 }
279
280 int sldns_wire2str_type_buf(uint16_t rrtype, char* s, size_t slen)
281 {
282         /* use arguments as temporary variables */
283         return sldns_wire2str_type_print(&s, &slen, rrtype);
284 }
285
286 int sldns_wire2str_class_buf(uint16_t rrclass, char* s, size_t slen)
287 {
288         /* use arguments as temporary variables */
289         return sldns_wire2str_class_print(&s, &slen, rrclass);
290 }
291
292 int sldns_wire2str_rcode_buf(int rcode, char* s, size_t slen)
293 {
294         /* use arguments as temporary variables */
295         return sldns_wire2str_rcode_print(&s, &slen, rcode);
296 }
297
298 int sldns_wire2str_opcode_buf(int opcode, char* s, size_t slen)
299 {
300         /* use arguments as temporary variables */
301         return sldns_wire2str_opcode_print(&s, &slen, opcode);
302 }
303
304 int sldns_wire2str_dname_buf(uint8_t* d, size_t dlen, char* s, size_t slen)
305 {
306         /* use arguments as temporary variables */
307         return sldns_wire2str_dname_scan(&d, &dlen, &s, &slen, NULL, 0);
308 }
309
310 int sldns_str_vprint(char** str, size_t* slen, const char* format, va_list args)
311 {
312         int w = vsnprintf(*str, *slen, format, args);
313         if(w < 0) {
314                 /* error in printout */
315                 return 0;
316         } else if((size_t)w >= *slen) {
317                 *str = NULL; /* we do not want str to point outside of buffer*/
318                 *slen = 0;
319         } else {
320                 *str += w;
321                 *slen -= w;
322         }
323         return w;
324 }
325
326 int sldns_str_print(char** str, size_t* slen, const char* format, ...)
327 {
328         int w;
329         va_list args;
330         va_start(args, format);
331         w = sldns_str_vprint(str, slen, format, args);
332         va_end(args);
333         return w;
334 }
335
336 /** print hex format into text buffer for specified length */
337 static int print_hex_buf(char** s, size_t* slen, uint8_t* buf, size_t len)
338 {
339         const char* hex = "0123456789ABCDEF";
340         size_t i;
341         for(i=0; i<len; i++) {
342                 (void)sldns_str_print(s, slen, "%c%c", hex[(buf[i]&0xf0)>>4],
343                         hex[buf[i]&0x0f]);
344         }
345         return (int)len*2;
346 }
347
348 /** print remainder of buffer in hex format with prefixed text */
349 static int print_remainder_hex(const char* pref, uint8_t** d, size_t* dlen,
350         char** s, size_t* slen)
351 {
352         int w = 0;
353         w += sldns_str_print(s, slen, "%s", pref);
354         w += print_hex_buf(s, slen, *d, *dlen);
355         *d += *dlen;
356         *dlen = 0;
357         return w;
358 }
359
360 int sldns_wire2str_pkt_scan(uint8_t** d, size_t* dlen, char** s, size_t* slen)
361 {
362         int w = 0;
363         unsigned qdcount, ancount, nscount, arcount, i;
364         uint8_t* pkt = *d;
365         size_t pktlen = *dlen;
366         if(*dlen >= LDNS_HEADER_SIZE) {
367                 qdcount = (unsigned)LDNS_QDCOUNT(*d);
368                 ancount = (unsigned)LDNS_ANCOUNT(*d);
369                 nscount = (unsigned)LDNS_NSCOUNT(*d);
370                 arcount = (unsigned)LDNS_ARCOUNT(*d);
371         } else {
372                 qdcount = ancount = nscount = arcount = 0;
373         }
374         w += sldns_wire2str_header_scan(d, dlen, s, slen);
375         w += sldns_str_print(s, slen, "\n");
376         w += sldns_str_print(s, slen, ";; QUESTION SECTION:\n");
377         for(i=0; i<qdcount; i++) {
378                 w += sldns_wire2str_rrquestion_scan(d, dlen, s, slen,
379                         pkt, pktlen);
380                 if(!*dlen) break;
381         }
382         w += sldns_str_print(s, slen, "\n");
383         w += sldns_str_print(s, slen, ";; ANSWER SECTION:\n");
384         for(i=0; i<ancount; i++) {
385                 w += sldns_wire2str_rr_scan(d, dlen, s, slen, pkt, pktlen);
386                 if(!*dlen) break;
387         }
388         w += sldns_str_print(s, slen, "\n");
389         w += sldns_str_print(s, slen, ";; AUTHORITY SECTION:\n");
390         for(i=0; i<nscount; i++) {
391                 w += sldns_wire2str_rr_scan(d, dlen, s, slen, pkt, pktlen);
392                 if(!*dlen) break;
393         }
394         w += sldns_str_print(s, slen, "\n");
395         w += sldns_str_print(s, slen, ";; ADDITIONAL SECTION:\n");
396         for(i=0; i<arcount; i++) {
397                 w += sldns_wire2str_rr_scan(d, dlen, s, slen, pkt, pktlen);
398                 if(!*dlen) break;
399         }
400         /* other fields: WHEN(time), SERVER(IP) not available here. */
401         w += sldns_str_print(s, slen, ";; MSG SIZE  rcvd: %d\n", (int)pktlen);
402         if(*dlen > 0) {
403                 w += print_remainder_hex(";; trailing garbage 0x",
404                         d, dlen, s, slen);
405                 w += sldns_str_print(s, slen, "\n");
406         }
407         return w;
408 }
409
410 /** scan type, class and ttl and printout, for rr */
411 static int sldns_rr_tcttl_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
412 {
413         int w = 0;
414         uint16_t t, c;
415         uint32_t ttl;
416         if(*dl < 8) {
417                 if(*dl < 4)
418                         return w + print_remainder_hex("; Error malformed 0x",
419                                 d, dl, s, sl);
420                 /* these print values or 0x.. if none left */
421                 t = sldns_read_uint16(*d);
422                 c = sldns_read_uint16((*d)+2);
423                 (*d)+=4;
424                 (*dl)-=4;
425                 w += sldns_wire2str_class_print(s, sl, c);
426                 w += sldns_str_print(s, sl, "\t");
427                 w += sldns_wire2str_type_print(s, sl, t);
428                 if(*dl == 0)
429                         return w + sldns_str_print(s, sl, "; Error no ttl");
430                 return w + print_remainder_hex(
431                         "; Error malformed ttl 0x", d, dl, s, sl);
432         }
433         t = sldns_read_uint16(*d);
434         c = sldns_read_uint16((*d)+2);
435         ttl = sldns_read_uint32((*d)+4);
436         (*d)+=8;
437         (*dl)-=8;
438         w += sldns_str_print(s, sl, "%lu\t", (unsigned long)ttl);
439         w += sldns_wire2str_class_print(s, sl, c);
440         w += sldns_str_print(s, sl, "\t");
441         w += sldns_wire2str_type_print(s, sl, t);
442         return w;
443 }
444
445 int sldns_wire2str_rr_scan(uint8_t** d, size_t* dlen, char** s, size_t* slen,
446         uint8_t* pkt, size_t pktlen)
447 {
448         int w = 0;
449         uint8_t* rr = *d;
450         size_t rrlen = *dlen, dname_off, rdlen, ordlen;
451         uint16_t rrtype = 0;
452         
453         if(*dlen >= 3 && (*d)[0]==0 &&
454                 sldns_read_uint16((*d)+1)==LDNS_RR_TYPE_OPT) {
455                 /* perform EDNS OPT processing */
456                 return sldns_wire2str_edns_scan(d, dlen, s, slen, pkt, pktlen);
457         }
458
459         /* try to scan the rdata with pretty-printing, but if that fails, then
460          * scan the rdata as an unknown RR type */
461         w += sldns_wire2str_dname_scan(d, dlen, s, slen, pkt, pktlen);
462         w += sldns_str_print(s, slen, "\t");
463         dname_off = rrlen-(*dlen);
464         if(*dlen == 4) {
465                 /* like a question-RR */
466                 uint16_t t = sldns_read_uint16(*d);
467                 uint16_t c = sldns_read_uint16((*d)+2);
468                 (*d)+=4;
469                 (*dlen)-=4;
470                 w += sldns_wire2str_class_print(s, slen, c);
471                 w += sldns_str_print(s, slen, "\t");
472                 w += sldns_wire2str_type_print(s, slen, t);
473                 w += sldns_str_print(s, slen, " ; Error no ttl,rdata\n");
474                 return w;
475         }
476         if(*dlen < 8) {
477                 if(*dlen == 0)
478                         return w + sldns_str_print(s, slen, ";Error missing RR\n");
479                 w += print_remainder_hex(";Error partial RR 0x", d, dlen, s, slen);
480                 return w + sldns_str_print(s, slen, "\n");
481         }
482         rrtype = sldns_read_uint16(*d);
483         w += sldns_rr_tcttl_scan(d, dlen, s, slen);
484         w += sldns_str_print(s, slen, "\t");
485
486         /* rdata */
487         if(*dlen < 2) {
488                 if(*dlen == 0)
489                         return w + sldns_str_print(s, slen, ";Error missing rdatalen\n");
490                 w += print_remainder_hex(";Error missing rdatalen 0x",
491                         d, dlen, s, slen);
492                 return w + sldns_str_print(s, slen, "\n");
493         }
494         rdlen = sldns_read_uint16(*d);
495         ordlen = rdlen;
496         (*d)+=2;
497         (*dlen)-=2;
498         if(*dlen < rdlen) {
499                 w += sldns_str_print(s, slen, "\\# %u ", (unsigned)rdlen);
500                 if(*dlen == 0)
501                         return w + sldns_str_print(s, slen, ";Error missing rdata\n");
502                 w += print_remainder_hex(";Error partial rdata 0x", d, dlen, s, slen);
503                 return w + sldns_str_print(s, slen, "\n");
504         }
505         w += sldns_wire2str_rdata_scan(d, &rdlen, s, slen, rrtype, pkt, pktlen);
506         (*dlen) -= (ordlen-rdlen);
507
508         /* default comment */
509         w += sldns_wire2str_rr_comment_print(s, slen, rr, rrlen, dname_off,
510                 rrtype);
511         w += sldns_str_print(s, slen, "\n");
512         return w;
513 }
514
515 int sldns_wire2str_rrquestion_scan(uint8_t** d, size_t* dlen, char** s,
516         size_t* slen, uint8_t* pkt, size_t pktlen)
517 {
518         int w = 0;
519         uint16_t t, c;
520         w += sldns_wire2str_dname_scan(d, dlen, s, slen, pkt, pktlen);
521         w += sldns_str_print(s, slen, "\t");
522         if(*dlen < 4) {
523                 if(*dlen == 0)
524                         return w + sldns_str_print(s, slen, "Error malformed\n");
525                 w += print_remainder_hex("Error malformed 0x", d, dlen, s, slen);
526                 return w + sldns_str_print(s, slen, "\n");
527         }
528         t = sldns_read_uint16(*d);
529         c = sldns_read_uint16((*d)+2);
530         (*d)+=4;
531         (*dlen)-=4;
532         w += sldns_wire2str_class_print(s, slen, c);
533         w += sldns_str_print(s, slen, "\t");
534         w += sldns_wire2str_type_print(s, slen, t);
535         w += sldns_str_print(s, slen, "\n");
536         return w;
537 }
538
539 int sldns_wire2str_rr_unknown_scan(uint8_t** d, size_t* dlen, char** s,
540         size_t* slen, uint8_t* pkt, size_t pktlen)
541 {
542         size_t rdlen, ordlen;
543         int w = 0;
544         w += sldns_wire2str_dname_scan(d, dlen, s, slen, pkt, pktlen);
545         w += sldns_str_print(s, slen, "\t");
546         w += sldns_rr_tcttl_scan(d, dlen, s, slen);
547         w += sldns_str_print(s, slen, "\t");
548         if(*dlen < 2) {
549                 if(*dlen == 0)
550                         return w + sldns_str_print(s, slen, ";Error missing rdatalen\n");
551                 w += print_remainder_hex(";Error missing rdatalen 0x",
552                         d, dlen, s, slen);
553                 return w + sldns_str_print(s, slen, "\n");
554         }
555         rdlen = sldns_read_uint16(*d);
556         ordlen = rdlen;
557         (*d) += 2;
558         (*dlen) -= 2;
559         if(*dlen < rdlen) {
560                 w += sldns_str_print(s, slen, "\\# %u ", (unsigned)rdlen);
561                 if(*dlen == 0)
562                         return w + sldns_str_print(s, slen, ";Error missing rdata\n");
563                 w += print_remainder_hex(";Error partial rdata 0x", d, dlen, s, slen);
564                 return w + sldns_str_print(s, slen, "\n");
565         }
566         w += sldns_wire2str_rdata_unknown_scan(d, &rdlen, s, slen);
567         (*dlen) -= (ordlen-rdlen);
568         w += sldns_str_print(s, slen, "\n");
569         return w;
570 }
571
572 /** print rr comment for type DNSKEY */
573 static int rr_comment_dnskey(char** s, size_t* slen, uint8_t* rr,
574         size_t rrlen, size_t dname_off)
575 {
576         size_t rdlen;
577         uint8_t* rdata;
578         int flags, w = 0;
579         if(rrlen < dname_off + 10) return 0;
580         rdlen = sldns_read_uint16(rr+dname_off+8);
581         if(rrlen < dname_off + 10 + rdlen) return 0;
582         rdata = rr + dname_off + 10;
583         flags = (int)sldns_read_uint16(rdata);
584         w += sldns_str_print(s, slen, " ;{");
585
586         /* id */
587         w += sldns_str_print(s, slen, "id = %u",
588                 sldns_calc_keytag_raw(rdata, rdlen));
589
590         /* flags */
591         if((flags&LDNS_KEY_ZONE_KEY)) {
592                 if((flags&LDNS_KEY_SEP_KEY))
593                         w += sldns_str_print(s, slen, " (ksk)");
594                 else    w += sldns_str_print(s, slen, " (zsk)");
595         }
596
597         /* keysize */
598         if(rdlen > 4) {
599                 w += sldns_str_print(s, slen, ", ");
600                 w += sldns_str_print(s, slen, "size = %db",
601                         (int)sldns_rr_dnskey_key_size_raw(
602                         (unsigned char*)rdata+4, rdlen-4, (int)(rdata[3])));
603         }
604
605         w += sldns_str_print(s, slen, "}");
606         return w;
607 }
608
609 /** print rr comment for type RRSIG */
610 static int rr_comment_rrsig(char** s, size_t* slen, uint8_t* rr,
611         size_t rrlen, size_t dname_off)
612 {
613         size_t rdlen;
614         uint8_t* rdata;
615         if(rrlen < dname_off + 10) return 0;
616         rdlen = sldns_read_uint16(rr+dname_off+8);
617         if(rrlen < dname_off + 10 + rdlen) return 0;
618         rdata = rr + dname_off + 10;
619         if(rdlen < 18) return 0;
620         return sldns_str_print(s, slen, " ;{id = %d}",
621                 (int)sldns_read_uint16(rdata+16));
622 }
623
624 /** print rr comment for type NSEC3 */
625 static int rr_comment_nsec3(char** s, size_t* slen, uint8_t* rr,
626         size_t rrlen, size_t dname_off)
627 {
628         size_t rdlen;
629         uint8_t* rdata;
630         int w = 0;
631         if(rrlen < dname_off + 10) return 0;
632         rdlen = sldns_read_uint16(rr+dname_off+8);
633         if(rrlen < dname_off + 10 + rdlen) return 0;
634         rdata = rr + dname_off + 10;
635         if(rdlen < 2) return 0;
636         if((rdata[1] & LDNS_NSEC3_VARS_OPTOUT_MASK))
637                 w += sldns_str_print(s, slen, " ;{flags: optout}");
638         return w;
639 }
640
641 int sldns_wire2str_rr_comment_print(char** s, size_t* slen, uint8_t* rr,
642         size_t rrlen, size_t dname_off, uint16_t rrtype)
643 {
644         if(rrtype == LDNS_RR_TYPE_DNSKEY) {
645                 return rr_comment_dnskey(s, slen, rr, rrlen, dname_off);
646         } else if(rrtype == LDNS_RR_TYPE_RRSIG) {
647                 return rr_comment_rrsig(s, slen, rr, rrlen, dname_off);
648         } else if(rrtype == LDNS_RR_TYPE_NSEC3) {
649                 return rr_comment_nsec3(s, slen, rr, rrlen, dname_off);
650         }
651         return 0;
652 }
653
654 int sldns_wire2str_header_scan(uint8_t** d, size_t* dlen, char** s,
655         size_t* slen)
656 {
657         int w = 0;
658         int opcode, rcode;
659         w += sldns_str_print(s, slen, ";; ->>HEADER<<- ");
660         if(*dlen == 0)
661                 return w+sldns_str_print(s, slen, "Error empty packet");
662         if(*dlen < 4)
663                 return w+print_remainder_hex("Error header too short 0x", d, dlen, s, slen);
664         opcode = (int)LDNS_OPCODE_WIRE(*d);
665         rcode = (int)LDNS_RCODE_WIRE(*d);
666         w += sldns_str_print(s, slen, "opcode: ");
667         w += sldns_wire2str_opcode_print(s, slen, opcode);
668         w += sldns_str_print(s, slen, ", ");
669         w += sldns_str_print(s, slen, "rcode: ");
670         w += sldns_wire2str_rcode_print(s, slen, rcode);
671         w += sldns_str_print(s, slen, ", ");
672         w += sldns_str_print(s, slen, "id: %d\n", (int)LDNS_ID_WIRE(*d));
673         w += sldns_str_print(s, slen, ";; flags:");
674         if(LDNS_QR_WIRE(*d)) w += sldns_str_print(s, slen, " qr");
675         if(LDNS_AA_WIRE(*d)) w += sldns_str_print(s, slen, " aa");
676         if(LDNS_TC_WIRE(*d)) w += sldns_str_print(s, slen, " tc");
677         if(LDNS_RD_WIRE(*d)) w += sldns_str_print(s, slen, " rd");
678         if(LDNS_CD_WIRE(*d)) w += sldns_str_print(s, slen, " cd");
679         if(LDNS_RA_WIRE(*d)) w += sldns_str_print(s, slen, " ra");
680         if(LDNS_AD_WIRE(*d)) w += sldns_str_print(s, slen, " ad");
681         if(LDNS_Z_WIRE(*d))  w += sldns_str_print(s, slen, " z");
682         w += sldns_str_print(s, slen, " ; ");
683         if(*dlen < LDNS_HEADER_SIZE)
684                 return w+print_remainder_hex("Error header too short 0x", d, dlen, s, slen);
685         w += sldns_str_print(s, slen, "QUERY: %d, ", (int)LDNS_QDCOUNT(*d));
686         w += sldns_str_print(s, slen, "ANSWER: %d, ", (int)LDNS_ANCOUNT(*d));
687         w += sldns_str_print(s, slen, "AUTHORITY: %d, ", (int)LDNS_NSCOUNT(*d));
688         w += sldns_str_print(s, slen, "ADDITIONAL: %d ", (int)LDNS_ARCOUNT(*d));
689         *d += LDNS_HEADER_SIZE;
690         *dlen -= LDNS_HEADER_SIZE;
691         return w;
692 }
693
694 int sldns_wire2str_rdata_scan(uint8_t** d, size_t* dlen, char** s,
695         size_t* slen, uint16_t rrtype, uint8_t* pkt, size_t pktlen)
696 {
697         /* try to prettyprint, but if that fails, use unknown format */
698         uint8_t* origd = *d;
699         char* origs = *s;
700         size_t origdlen = *dlen, origslen = *slen;
701         size_t r_cnt, r_max;
702         sldns_rdf_type rdftype;
703         int w = 0, n;
704
705         const sldns_rr_descriptor *desc = sldns_rr_descript(rrtype);
706         if(!desc) /* unknown format */
707                 return sldns_wire2str_rdata_unknown_scan(d, dlen, s, slen);
708         /* dlen equals the rdatalen for the rdata */
709
710         r_max = sldns_rr_descriptor_maximum(desc);
711         for(r_cnt=0; r_cnt < r_max; r_cnt++) {
712                 if(*dlen == 0) {
713                         if(r_cnt < sldns_rr_descriptor_minimum(desc))
714                                 goto failed;
715                         break; /* nothing more to print */
716                 }
717                 rdftype = sldns_rr_descriptor_field_type(desc, r_cnt);
718                 if(r_cnt != 0)
719                         w += sldns_str_print(s, slen, " ");
720                 n = sldns_wire2str_rdf_scan(d, dlen, s, slen, rdftype,
721                         pkt, pktlen);
722                 if(n == -1) {
723                 failed:
724                         /* failed, use unknown format */
725                         *d = origd; *s = origs;
726                         *dlen = origdlen; *slen = origslen;
727                         return sldns_wire2str_rdata_unknown_scan(d, dlen,
728                                 s, slen);
729                 }
730                 w += n;
731         }
732         if(*dlen != 0) {
733                 goto failed;
734         }
735         return w;
736 }
737
738 int sldns_wire2str_rdata_unknown_scan(uint8_t** d, size_t* dlen, char** s,
739         size_t* slen)
740 {
741         int w = 0;
742
743         /* print length */
744         w += sldns_str_print(s, slen, "\\# %u", (unsigned)*dlen);
745
746         /* print rdlen in hex */
747         if(*dlen != 0)
748                 w += sldns_str_print(s, slen, " ");
749         w += print_hex_buf(s, slen, *d, *dlen);
750         (*d) += *dlen;
751         (*dlen) = 0;
752         return w;
753 }
754
755 /** print and escape one character for a domain dname */
756 static int dname_char_print(char** s, size_t* slen, uint8_t c)
757 {
758         if(c == '.' || c == ';' || c == '(' || c == ')' || c == '\\')
759                 return sldns_str_print(s, slen, "\\%c", c);
760         else if(!(isascii((unsigned char)c) && isgraph((unsigned char)c)))
761                 return sldns_str_print(s, slen, "\\%03u", (unsigned)c);
762         /* plain printout */
763         if(*slen) {
764                 **s = (char)c;
765                 (*s)++;
766                 (*slen)--;
767         }
768         return 1;
769 }
770
771 int sldns_wire2str_dname_scan(uint8_t** d, size_t* dlen, char** s, size_t* slen,
772         uint8_t* pkt, size_t pktlen)
773 {
774         int w = 0;
775         /* spool labels onto the string, use compression if its there */
776         uint8_t* pos = *d;
777         unsigned i, counter=0;
778         const unsigned maxcompr = 1000; /* loop detection, max compr ptrs */
779         int in_buf = 1;
780         if(*dlen == 0) return sldns_str_print(s, slen, "ErrorMissingDname");
781         if(*pos == 0) {
782                 (*d)++;
783                 (*dlen)--;
784                 return sldns_str_print(s, slen, ".");
785         }
786         while(*pos) {
787                 /* read label length */
788                 uint8_t labellen = *pos++;
789                 if(in_buf) { (*d)++; (*dlen)--; }
790
791                 /* find out what sort of label we have */
792                 if((labellen&0xc0) == 0xc0) {
793                         /* compressed */
794                         uint16_t target = 0;
795                         if(in_buf && *dlen == 0)
796                                 return w + sldns_str_print(s, slen,
797                                         "ErrorPartialDname");
798                         else if(!in_buf && pos+1 > pkt+pktlen)
799                                 return w + sldns_str_print(s, slen,
800                                         "ErrorPartialDname");
801                         target = ((labellen&0x3f)<<8) | *pos;
802                         if(in_buf) { (*d)++; (*dlen)--; }
803                         /* move to target, if possible */
804                         if(!pkt || target >= pktlen)
805                                 return w + sldns_str_print(s, slen,
806                                         "ErrorComprPtrOutOfBounds");
807                         if(counter++ > maxcompr)
808                                 return w + sldns_str_print(s, slen,
809                                         "ErrorComprPtrLooped");
810                         in_buf = 0;
811                         pos = pkt+target;
812                         continue;
813                 } else if((labellen&0xc0)) {
814                         /* notimpl label type */
815                         w += sldns_str_print(s, slen,
816                                 "ErrorLABELTYPE%xIsUnknown",
817                                 (int)(labellen&0xc0));
818                         return w;
819                 }
820
821                 /* spool label characters, end with '.' */
822                 if(in_buf && *dlen < (size_t)labellen)
823                         labellen = (uint8_t)*dlen;
824                 else if(!in_buf && pos+(size_t)labellen > pkt+pktlen)
825                         labellen = (uint8_t)(pkt + pktlen - pos);
826                 for(i=0; i<(unsigned)labellen; i++) {
827                         w += dname_char_print(s, slen, *pos++);
828                 }
829                 if(in_buf) {
830                         (*d) += labellen;
831                         (*dlen) -= labellen;
832                         if(*dlen == 0) break;
833                 }
834                 w += sldns_str_print(s, slen, ".");
835         }
836         /* skip over final root label */
837         if(in_buf && *dlen > 0) { (*d)++; (*dlen)--; }
838         /* in case we printed no labels, terminate dname */
839         if(w == 0) w += sldns_str_print(s, slen, ".");
840         return w;
841 }
842
843 int sldns_wire2str_opcode_print(char** s, size_t* slen, int opcode)
844 {
845         sldns_lookup_table *lt = sldns_lookup_by_id(sldns_opcodes, opcode);
846         if (lt && lt->name) {
847                 return sldns_str_print(s, slen, "%s", lt->name);
848         }
849         return sldns_str_print(s, slen, "OPCODE%u", (unsigned)opcode);
850 }
851
852 int sldns_wire2str_rcode_print(char** s, size_t* slen, int rcode)
853 {
854         sldns_lookup_table *lt = sldns_lookup_by_id(sldns_rcodes, rcode);
855         if (lt && lt->name) {
856                 return sldns_str_print(s, slen, "%s", lt->name);
857         }
858         return sldns_str_print(s, slen, "RCODE%u", (unsigned)rcode);
859 }
860
861 int sldns_wire2str_class_print(char** s, size_t* slen, uint16_t rrclass)
862 {
863         sldns_lookup_table *lt = sldns_lookup_by_id(sldns_rr_classes,
864                 (int)rrclass);
865         if (lt && lt->name) {
866                 return sldns_str_print(s, slen, "%s", lt->name);
867         }
868         return sldns_str_print(s, slen, "CLASS%u", (unsigned)rrclass);
869 }
870
871 int sldns_wire2str_type_print(char** s, size_t* slen, uint16_t rrtype)
872 {
873         const sldns_rr_descriptor *descriptor = sldns_rr_descript(rrtype);
874         if (descriptor && descriptor->_name) {
875                 return sldns_str_print(s, slen, "%s", descriptor->_name);
876         }
877         return sldns_str_print(s, slen, "TYPE%u", (unsigned)rrtype);
878 }
879
880 int sldns_wire2str_edns_option_code_print(char** s, size_t* slen,
881         uint16_t opcode)
882 {
883         sldns_lookup_table *lt = sldns_lookup_by_id(sldns_edns_options,
884                 (int)opcode);
885         if (lt && lt->name) {
886                 return sldns_str_print(s, slen, "%s", lt->name);
887         }
888         return sldns_str_print(s, slen, "OPT%u", (unsigned)opcode);
889 }
890
891 int sldns_wire2str_class_scan(uint8_t** d, size_t* dlen, char** s, size_t* slen)
892 {
893         uint16_t c;
894         if(*dlen == 0) return 0;
895         if(*dlen < 2) return print_remainder_hex("Error malformed 0x", d, dlen, s, slen);
896         c = sldns_read_uint16(*d);
897         (*d)+=2;
898         (*dlen)-=2;
899         return sldns_wire2str_class_print(s, slen, c);
900 }
901
902 int sldns_wire2str_type_scan(uint8_t** d, size_t* dlen, char** s, size_t* slen)
903 {
904         uint16_t t;
905         if(*dlen == 0) return 0;
906         if(*dlen < 2) return print_remainder_hex("Error malformed 0x", d, dlen, s, slen);
907         t = sldns_read_uint16(*d);
908         (*d)+=2;
909         (*dlen)-=2;
910         return sldns_wire2str_type_print(s, slen, t);
911 }
912
913 int sldns_wire2str_ttl_scan(uint8_t** d, size_t* dlen, char** s, size_t* slen)
914 {
915         uint32_t ttl;
916         if(*dlen == 0) return 0;
917         if(*dlen < 4) return print_remainder_hex("Error malformed 0x", d, dlen, s, slen);
918         ttl = sldns_read_uint32(*d);
919         (*d)+=4;
920         (*dlen)-=4;
921         return sldns_str_print(s, slen, "%u", (unsigned)ttl);
922 }
923
924 int sldns_wire2str_rdf_scan(uint8_t** d, size_t* dlen, char** s, size_t* slen,
925         int rdftype, uint8_t* pkt, size_t pktlen)
926 {
927         if(*dlen == 0) return 0;
928         switch(rdftype) {
929         case LDNS_RDF_TYPE_NONE:
930                 return 0;
931         case LDNS_RDF_TYPE_DNAME:
932                 return sldns_wire2str_dname_scan(d, dlen, s, slen, pkt, pktlen);
933         case LDNS_RDF_TYPE_INT8:
934                 return sldns_wire2str_int8_scan(d, dlen, s, slen);
935         case LDNS_RDF_TYPE_INT16:
936                 return sldns_wire2str_int16_scan(d, dlen, s, slen);
937         case LDNS_RDF_TYPE_INT32:
938                 return sldns_wire2str_int32_scan(d, dlen, s, slen);
939         case LDNS_RDF_TYPE_PERIOD:
940                 return sldns_wire2str_period_scan(d, dlen, s, slen);
941         case LDNS_RDF_TYPE_TSIGTIME:
942                 return sldns_wire2str_tsigtime_scan(d, dlen, s, slen);
943         case LDNS_RDF_TYPE_A:
944                 return sldns_wire2str_a_scan(d, dlen, s, slen);
945         case LDNS_RDF_TYPE_AAAA:
946                 return sldns_wire2str_aaaa_scan(d, dlen, s, slen);
947         case LDNS_RDF_TYPE_STR:
948                 return sldns_wire2str_str_scan(d, dlen, s, slen);
949         case LDNS_RDF_TYPE_APL:
950                 return sldns_wire2str_apl_scan(d, dlen, s, slen);
951         case LDNS_RDF_TYPE_B32_EXT:
952                 return sldns_wire2str_b32_ext_scan(d, dlen, s, slen);
953         case LDNS_RDF_TYPE_B64:
954                 return sldns_wire2str_b64_scan(d, dlen, s, slen);
955         case LDNS_RDF_TYPE_HEX:
956                 return sldns_wire2str_hex_scan(d, dlen, s, slen);
957         case LDNS_RDF_TYPE_NSEC:
958                 return sldns_wire2str_nsec_scan(d, dlen, s, slen);
959         case LDNS_RDF_TYPE_NSEC3_SALT:
960                 return sldns_wire2str_nsec3_salt_scan(d, dlen, s, slen);
961         case LDNS_RDF_TYPE_TYPE:
962                 return sldns_wire2str_type_scan(d, dlen, s, slen);
963         case LDNS_RDF_TYPE_CLASS:
964                 return sldns_wire2str_class_scan(d, dlen, s, slen);
965         case LDNS_RDF_TYPE_CERT_ALG:
966                 return sldns_wire2str_cert_alg_scan(d, dlen, s, slen);
967         case LDNS_RDF_TYPE_ALG:
968                 return sldns_wire2str_alg_scan(d, dlen, s, slen);
969         case LDNS_RDF_TYPE_UNKNOWN:
970                 return sldns_wire2str_unknown_scan(d, dlen, s, slen);
971         case LDNS_RDF_TYPE_TIME:
972                 return sldns_wire2str_time_scan(d, dlen, s, slen);
973         case LDNS_RDF_TYPE_LOC:
974                 return sldns_wire2str_loc_scan(d, dlen, s, slen);
975         case LDNS_RDF_TYPE_WKS:
976         case LDNS_RDF_TYPE_SERVICE:
977                 return sldns_wire2str_wks_scan(d, dlen, s, slen);
978         case LDNS_RDF_TYPE_NSAP:
979                 return sldns_wire2str_nsap_scan(d, dlen, s, slen);
980         case LDNS_RDF_TYPE_ATMA:
981                 return sldns_wire2str_atma_scan(d, dlen, s, slen);
982         case LDNS_RDF_TYPE_IPSECKEY:
983                 return sldns_wire2str_ipseckey_scan(d, dlen, s, slen, pkt,
984                         pktlen);
985         case LDNS_RDF_TYPE_HIP:
986                 return sldns_wire2str_hip_scan(d, dlen, s, slen);
987         case LDNS_RDF_TYPE_INT16_DATA:
988                 return sldns_wire2str_int16_data_scan(d, dlen, s, slen);
989         case LDNS_RDF_TYPE_NSEC3_NEXT_OWNER:
990                 return sldns_wire2str_b32_ext_scan(d, dlen, s, slen);
991         case LDNS_RDF_TYPE_ILNP64:
992                 return sldns_wire2str_ilnp64_scan(d, dlen, s, slen);
993         case LDNS_RDF_TYPE_EUI48:
994                 return sldns_wire2str_eui48_scan(d, dlen, s, slen);
995         case LDNS_RDF_TYPE_EUI64:
996                 return sldns_wire2str_eui64_scan(d, dlen, s, slen);
997         case LDNS_RDF_TYPE_TAG:
998                 return sldns_wire2str_tag_scan(d, dlen, s, slen);
999         case LDNS_RDF_TYPE_LONG_STR:
1000                 return sldns_wire2str_long_str_scan(d, dlen, s, slen);
1001         case LDNS_RDF_TYPE_TSIGERROR:
1002                 return sldns_wire2str_tsigerror_scan(d, dlen, s, slen);
1003         }
1004         /* unknown rdf type */
1005         return -1;
1006 }
1007
1008 int sldns_wire2str_int8_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
1009 {
1010         int w;
1011         if(*dl < 1) return -1;
1012         w = sldns_str_print(s, sl, "%u", (unsigned)**d);
1013         (*d)++;
1014         (*dl)--;
1015         return w;
1016 }
1017
1018 int sldns_wire2str_int16_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
1019 {
1020         int w;
1021         if(*dl < 2) return -1;
1022         w = sldns_str_print(s, sl, "%lu", (unsigned long)sldns_read_uint16(*d));
1023         (*d)+=2;
1024         (*dl)-=2;
1025         return w;
1026 }
1027
1028 int sldns_wire2str_int32_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
1029 {
1030         int w;
1031         if(*dl < 4) return -1;
1032         w = sldns_str_print(s, sl, "%lu", (unsigned long)sldns_read_uint32(*d));
1033         (*d)+=4;
1034         (*dl)-=4;
1035         return w;
1036 }
1037
1038 int sldns_wire2str_period_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
1039 {
1040         int w;
1041         if(*dl < 4) return -1;
1042         w = sldns_str_print(s, sl, "%u", (unsigned)sldns_read_uint32(*d));
1043         (*d)+=4;
1044         (*dl)-=4;
1045         return w;
1046 }
1047
1048 int sldns_wire2str_tsigtime_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
1049 {
1050         /* tsigtime is 48 bits network order unsigned integer */
1051         int w;
1052         uint64_t tsigtime = 0;
1053         uint64_t d0, d1, d2, d3, d4, d5;
1054         if(*dl < 6) return -1;
1055         d0 = (*d)[0]; /* cast to uint64 for shift operations */
1056         d1 = (*d)[1];
1057         d2 = (*d)[2];
1058         d3 = (*d)[3];
1059         d4 = (*d)[4];
1060         d5 = (*d)[5];
1061         tsigtime = (d0<<40) | (d1<<32) | (d2<<24) | (d3<<16) | (d4<<8) | d5;
1062 #ifndef USE_WINSOCK
1063         w = sldns_str_print(s, sl, "%llu", (long long)tsigtime);
1064 #else
1065         w = sldns_str_print(s, sl, "%I64u", (long long)tsigtime);
1066 #endif
1067         (*d)+=6;
1068         (*dl)-=6;
1069         return w;
1070 }
1071
1072 int sldns_wire2str_a_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
1073 {
1074         char buf[32];
1075         int w;
1076         if(*dl < 4) return -1;
1077         if(!inet_ntop(AF_INET, *d, buf, (socklen_t)sizeof(buf)))
1078                 return -1;
1079         w = sldns_str_print(s, sl, "%s", buf);
1080         (*d)+=4;
1081         (*dl)-=4;
1082         return w;
1083 }
1084
1085 int sldns_wire2str_aaaa_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
1086 {
1087 #ifdef AF_INET6
1088         char buf[64];
1089         int w;
1090         if(*dl < 16) return -1;
1091         if(!inet_ntop(AF_INET6, *d, buf, (socklen_t)sizeof(buf)))
1092                 return -1;
1093         w = sldns_str_print(s, sl, "%s", buf);
1094         (*d)+=16;
1095         (*dl)-=16;
1096         return w;
1097 #else
1098         return -1;
1099 #endif
1100 }
1101
1102 /** printout escaped TYPE_STR character */
1103 static int str_char_print(char** s, size_t* sl, uint8_t c)
1104 {
1105         if(isprint((unsigned char)c) || c == '\t') {
1106                 if(c == '\"' || c == '\\')
1107                         return sldns_str_print(s, sl, "\\%c", c);
1108                 if(*sl) {
1109                         **s = (char)c;
1110                         (*s)++;
1111                         (*sl)--;
1112                 }
1113                 return 1;
1114         }
1115         return sldns_str_print(s, sl, "\\%03u", (unsigned)c);
1116 }
1117
1118 int sldns_wire2str_str_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
1119 {
1120         int w = 0;
1121         size_t i, len;
1122         if(*dl < 1) return -1;
1123         len = **d;
1124         if(*dl < 1+len) return -1;
1125         (*d)++;
1126         (*dl)--;
1127         w += sldns_str_print(s, sl, "\"");
1128         for(i=0; i<len; i++)
1129                 w += str_char_print(s, sl, (*d)[i]);
1130         w += sldns_str_print(s, sl, "\"");
1131         (*d)+=len;
1132         (*dl)-=len;
1133         return w;
1134 }
1135
1136 int sldns_wire2str_apl_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
1137 {
1138         int i, w = 0;
1139         uint16_t family;
1140         uint8_t negation, prefix, adflength;
1141         if(*dl < 4) return -1;
1142         family = sldns_read_uint16(*d);
1143         prefix = (*d)[2];
1144         negation = ((*d)[3] & LDNS_APL_NEGATION);
1145         adflength = ((*d)[3] & LDNS_APL_MASK);
1146         if(*dl < 4+(size_t)adflength) return -1;
1147         if(family != LDNS_APL_IP4 && family != LDNS_APL_IP6)
1148                 return -1; /* unknown address family */
1149         if(negation)
1150                 w += sldns_str_print(s, sl, "!");
1151         w += sldns_str_print(s, sl, "%u:", (unsigned)family);
1152         if(family == LDNS_APL_IP4) {
1153                 /* check if prefix <32 ? */
1154                 /* address is variable length 0 - 4 */
1155                 for(i=0; i<4; i++) {
1156                         if(i > 0)
1157                                 w += sldns_str_print(s, sl, ".");
1158                         if(i < (int)adflength)
1159                                 w += sldns_str_print(s, sl, "%d", (*d)[4+i]);
1160                         else    w += sldns_str_print(s, sl, "0");
1161                 }
1162         } else if(family == LDNS_APL_IP6) {
1163                 /* check if prefix <128 ? */
1164                 /* address is variable length 0 - 16 */
1165                 for(i=0; i<16; i++) {
1166                         if(i%2 == 0 && i>0)
1167                                 w += sldns_str_print(s, sl, ":");
1168                         if(i < (int)adflength)
1169                                 w += sldns_str_print(s, sl, "%02x", (*d)[4+i]);
1170                         else    w += sldns_str_print(s, sl, "00");
1171                 }
1172         }
1173         w += sldns_str_print(s, sl, "/%u", (unsigned)prefix);
1174         (*d) += 4+adflength;
1175         (*dl) -= 4+adflength;
1176         return w;
1177 }
1178
1179 int sldns_wire2str_b32_ext_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
1180 {
1181         size_t datalen;
1182         size_t sz;
1183         if(*dl < 1) return -1;
1184         datalen = (*d)[0];
1185         if(*dl < 1+datalen) return -1;
1186         sz = sldns_b32_ntop_calculate_size(datalen);
1187         if(*sl < sz+1) {
1188                 (*d) += datalen+1;
1189                 (*dl) -= (datalen+1);
1190                 return (int)sz; /* out of space really, but would need buffer
1191                         in order to truncate the output */
1192         }
1193         sldns_b32_ntop_extended_hex((*d)+1, datalen, *s, *sl);
1194         (*d) += datalen+1;
1195         (*dl) -= (datalen+1);
1196         (*s) += sz;
1197         (*sl) -= sz;
1198         return (int)sz;
1199 }
1200
1201 /** scan number of bytes from wire into b64 presentation format */
1202 static int sldns_wire2str_b64_scan_num(uint8_t** d, size_t* dl, char** s,
1203         size_t* sl, size_t num)
1204 {
1205         /* b64_ntop_calculate size includes null at the end */
1206         size_t sz = sldns_b64_ntop_calculate_size(num)-1;
1207         if(*sl < sz+1) {
1208                 (*d) += num;
1209                 (*dl) -= num;
1210                 return (int)sz; /* out of space really, but would need buffer
1211                         in order to truncate the output */
1212         }
1213         sldns_b64_ntop(*d, num, *s, *sl);
1214         (*d) += num;
1215         (*dl) -= num;
1216         (*s) += sz;
1217         (*sl) -= sz;
1218         return (int)sz;
1219 }
1220
1221 int sldns_wire2str_b64_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
1222 {
1223         if(*dl == 0) {
1224                 return sldns_str_print(s, sl, "0");
1225         }
1226         return sldns_wire2str_b64_scan_num(d, dl, s, sl, *dl);
1227 }
1228
1229 int sldns_wire2str_hex_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
1230 {
1231         if(*dl == 0) {
1232                 return sldns_str_print(s, sl, "0");
1233         }
1234         return print_remainder_hex("", d, dl, s, sl);
1235 }
1236
1237 int sldns_wire2str_nsec_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
1238 {
1239         uint8_t* p = *d;
1240         size_t pl = *dl;
1241         unsigned i, bit, window, block_len;
1242         uint16_t t;
1243         int w = 0;
1244         
1245         /* check for errors */
1246         while(pl) {
1247                 if(pl < 2) return -1;
1248                 block_len = (unsigned)p[1];
1249                 if(pl < 2+block_len) return -1;
1250                 p += block_len+2;
1251                 pl -= block_len+2;
1252         }
1253
1254         /* do it */
1255         p = *d;
1256         pl = *dl;
1257         while(pl) {
1258                 if(pl < 2) return -1; /* cannot happen */
1259                 window = (unsigned)p[0];
1260                 block_len = (unsigned)p[1];
1261                 if(pl < 2+block_len) return -1; /* cannot happen */
1262                 p += 2;
1263                 for(i=0; i<block_len; i++) {
1264                         if(p[i] == 0) continue;
1265                         /* base type number for this octet */
1266                         t = ((window)<<8) | (i << 3);
1267                         for(bit=0; bit<8; bit++) {
1268                                 if((p[i]&(0x80>>bit))) {
1269                                         if(w) w += sldns_str_print(s, sl, " ");
1270                                         w += sldns_wire2str_type_print(s, sl,
1271                                                 t+bit);
1272                                 }
1273                         }
1274                 }
1275                 p += block_len;
1276                 pl -= block_len+2;
1277         }
1278         (*d) += *dl;
1279         (*dl) = 0;
1280         return w;
1281 }
1282
1283 int sldns_wire2str_nsec3_salt_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
1284 {
1285         size_t salt_len;
1286         int w;
1287         if(*dl < 1) return -1;
1288         salt_len = (size_t)(*d)[0];
1289         if(*dl < 1+salt_len) return -1;
1290         (*d)++;
1291         (*dl)--;
1292         if(salt_len == 0) {
1293                 return sldns_str_print(s, sl, "-");
1294         }
1295         w = print_hex_buf(s, sl, *d, salt_len);
1296         (*dl)-=salt_len;
1297         (*d)+=salt_len;
1298         return w;
1299 }
1300
1301 int sldns_wire2str_cert_alg_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
1302 {
1303         sldns_lookup_table *lt;
1304         int data, w;
1305         if(*dl < 2) return -1;
1306         data = (int)sldns_read_uint16(*d);
1307         lt = sldns_lookup_by_id(sldns_cert_algorithms, data);
1308         if(lt && lt->name)
1309                 w = sldns_str_print(s, sl, "%s", lt->name);
1310         else    w = sldns_str_print(s, sl, "%d", data);
1311         (*dl)-=2;
1312         (*d)+=2;
1313         return w;
1314 }
1315
1316 int sldns_wire2str_alg_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
1317 {
1318         /* don't use algorithm mnemonics in the presentation format
1319          * this kind of got sneaked into the rfc's */
1320         return sldns_wire2str_int8_scan(d, dl, s, sl);
1321 }
1322
1323 int sldns_wire2str_unknown_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
1324 {
1325         return sldns_wire2str_rdata_unknown_scan(d, dl, s, sl);
1326 }
1327
1328 int sldns_wire2str_time_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
1329 {
1330         /* create a YYYYMMDDHHMMSS string if possible */
1331         struct tm tm;
1332         char date_buf[16];
1333         uint32_t t;
1334         memset(&tm, 0, sizeof(tm));
1335         if(*dl < 4) return -1;
1336         t = sldns_read_uint32(*d);
1337         date_buf[15]=0;
1338         if(sldns_serial_arithmitics_gmtime_r(t, time(NULL), &tm) &&
1339                 strftime(date_buf, 15, "%Y%m%d%H%M%S", &tm)) {
1340                 (*d) += 4;
1341                 (*dl) -= 4;
1342                 return sldns_str_print(s, sl, "%s", date_buf);
1343         }
1344         return -1;
1345 }
1346
1347 static int
1348 loc_cm_print(char** str, size_t* sl, uint8_t mantissa, uint8_t exponent)
1349 {
1350         int w = 0;
1351         uint8_t i;
1352         /* is it 0.<two digits> ? */
1353         if(exponent < 2) {
1354                 if(exponent == 1)
1355                         mantissa *= 10;
1356                 return sldns_str_print(str, sl, "0.%02ld", (long)mantissa);
1357         }
1358         /* always <digit><string of zeros> */
1359         w += sldns_str_print(str, sl, "%d", (int)mantissa);
1360         for(i=0; i<exponent-2; i++)
1361                 w += sldns_str_print(str, sl, "0");
1362         return w;
1363 }
1364
1365 int sldns_wire2str_loc_scan(uint8_t** d, size_t* dl, char** str, size_t* sl)
1366 {
1367         /* we could do checking (ie degrees < 90 etc)? */
1368         uint8_t version;
1369         uint8_t size;
1370         uint8_t horizontal_precision;
1371         uint8_t vertical_precision;
1372         uint32_t longitude;
1373         uint32_t latitude;
1374         uint32_t altitude;
1375         char northerness;
1376         char easterness;
1377         uint32_t h;
1378         uint32_t m;
1379         double s;
1380         uint32_t equator = (uint32_t)1 << 31; /* 2**31 */
1381         int w = 0;
1382
1383         if(*dl < 16) return -1;
1384         version = (*d)[0];
1385         if(version != 0)
1386                 return sldns_wire2str_hex_scan(d, dl, str, sl);
1387         size = (*d)[1];
1388         horizontal_precision = (*d)[2];
1389         vertical_precision = (*d)[3];
1390
1391         latitude = sldns_read_uint32((*d)+4);
1392         longitude = sldns_read_uint32((*d)+8);
1393         altitude = sldns_read_uint32((*d)+12);
1394
1395         if (latitude > equator) {
1396                 northerness = 'N';
1397                 latitude = latitude - equator;
1398         } else {
1399                 northerness = 'S';
1400                 latitude = equator - latitude;
1401         }
1402         h = latitude / (1000 * 60 * 60);
1403         latitude = latitude % (1000 * 60 * 60);
1404         m = latitude / (1000 * 60);
1405         latitude = latitude % (1000 * 60);
1406         s = (double) latitude / 1000.0;
1407         w += sldns_str_print(str, sl, "%02u %02u %06.3f %c ",
1408                 h, m, s, northerness);
1409
1410         if (longitude > equator) {
1411                 easterness = 'E';
1412                 longitude = longitude - equator;
1413         } else {
1414                 easterness = 'W';
1415                 longitude = equator - longitude;
1416         }
1417         h = longitude / (1000 * 60 * 60);
1418         longitude = longitude % (1000 * 60 * 60);
1419         m = longitude / (1000 * 60);
1420         longitude = longitude % (1000 * 60);
1421         s = (double) longitude / (1000.0);
1422         w += sldns_str_print(str, sl, "%02u %02u %06.3f %c ",
1423                 h, m, s, easterness);
1424
1425         s = ((double) altitude) / 100;
1426         s -= 100000;
1427
1428         if(altitude%100 != 0)
1429                 w += sldns_str_print(str, sl, "%.2f", s);
1430         else
1431                 w += sldns_str_print(str, sl, "%.0f", s);
1432
1433         w += sldns_str_print(str, sl, "m ");
1434
1435         w += loc_cm_print(str, sl, (size & 0xf0) >> 4, size & 0x0f);
1436         w += sldns_str_print(str, sl, "m ");
1437
1438         w += loc_cm_print(str, sl, (horizontal_precision & 0xf0) >> 4,
1439                 horizontal_precision & 0x0f);
1440         w += sldns_str_print(str, sl, "m ");
1441
1442         w += loc_cm_print(str, sl, (vertical_precision & 0xf0) >> 4,
1443                 vertical_precision & 0x0f);
1444         w += sldns_str_print(str, sl, "m");
1445
1446         (*d)+=16;
1447         (*dl)-=16;
1448         return w;
1449 }
1450
1451 int sldns_wire2str_wks_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
1452 {
1453         /* protocol, followed by bitmap of services */
1454         const char* proto_name = NULL;
1455         struct protoent *protocol;
1456         struct servent *service;
1457         uint8_t protocol_nr;
1458         int bit, port, w = 0;
1459         size_t i;
1460         /* we cannot print with strings because they
1461          * are not portable, the presentation format may
1462          * not be able to be read in on another computer.  */
1463         int print_symbols = 0;
1464
1465         /* protocol */
1466         if(*dl < 1) return -1;
1467         protocol_nr = (*d)[0];
1468         (*d)++;
1469         (*dl)--;
1470         protocol = getprotobynumber((int)protocol_nr);
1471         if(protocol && (protocol->p_name != NULL)) {
1472                 w += sldns_str_print(s, sl, "%s", protocol->p_name);
1473                 proto_name = protocol->p_name;
1474         } else if(protocol_nr == 6) {
1475                 w += sldns_str_print(s, sl, "tcp");
1476         } else if(protocol_nr == 17) {
1477                 w += sldns_str_print(s, sl, "udp");
1478         } else  {
1479                 w += sldns_str_print(s, sl, "%u", (unsigned)protocol_nr);
1480         }
1481
1482         for(i=0; i<*dl; i++) {
1483                 if((*d)[i] == 0)
1484                         continue;
1485                 for(bit=0; bit<8; bit++) {
1486                         if(!(((*d)[i])&(0x80>>bit)))
1487                                 continue;
1488                         port = (int)i*8 + bit;
1489
1490                         if(!print_symbols)
1491                                 service = NULL;
1492                         else
1493                                 service = getservbyport(
1494                                         (int)htons((uint16_t)port), proto_name);
1495                         if(service && service->s_name)
1496                                 w += sldns_str_print(s, sl, " %s",
1497                                         service->s_name);
1498                         else    w += sldns_str_print(s, sl, " %u",
1499                                         (unsigned)port);
1500                 }
1501         }
1502
1503 #ifdef HAVE_ENDSERVENT
1504         endservent();
1505 #endif
1506 #ifdef HAVE_ENDPROTOENT
1507         endprotoent();
1508 #endif
1509         (*d) += *dl;
1510         (*dl) = 0;
1511         return w;
1512 }
1513
1514 int sldns_wire2str_nsap_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
1515 {
1516         return print_remainder_hex("0x", d, dl, s, sl);
1517 }
1518
1519 int sldns_wire2str_atma_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
1520 {
1521         return print_remainder_hex("", d, dl, s, sl);
1522 }
1523
1524 /* internal scan routine that can modify arguments on failure */
1525 static int sldns_wire2str_ipseckey_scan_internal(uint8_t** d, size_t* dl,
1526         char** s, size_t* sl, uint8_t* pkt, size_t pktlen)
1527 {
1528         /* http://www.ietf.org/internet-drafts/draft-ietf-ipseckey-rr-12.txt*/
1529         uint8_t precedence, gateway_type, algorithm;
1530         int w = 0;
1531
1532         if(*dl < 3) return -1;
1533         precedence = (*d)[0];
1534         gateway_type = (*d)[1];
1535         algorithm = (*d)[2];
1536         if(gateway_type > 3)
1537                 return -1; /* unknown */
1538         (*d)+=3;
1539         (*dl)-=3;
1540         w += sldns_str_print(s, sl, "%d %d %d ",
1541                 (int)precedence, (int)gateway_type, (int)algorithm);
1542
1543         switch(gateway_type) {
1544         case 0: /* no gateway */
1545                 w += sldns_str_print(s, sl, ".");
1546                 break;
1547         case 1: /* ip4 */
1548                 w += sldns_wire2str_a_scan(d, dl, s, sl);
1549                 break;
1550         case 2: /* ip6 */
1551                 w += sldns_wire2str_aaaa_scan(d, dl, s, sl);
1552                 break;
1553         case 3: /* dname */
1554                 w += sldns_wire2str_dname_scan(d, dl, s, sl, pkt, pktlen);
1555                 break;
1556         default: /* unknown */
1557                 return -1;
1558         }
1559
1560         if(*dl < 1)
1561                 return -1;
1562         w += sldns_str_print(s, sl, " ");
1563         w += sldns_wire2str_b64_scan_num(d, dl, s, sl, *dl);
1564         return w;
1565 }
1566
1567 int sldns_wire2str_ipseckey_scan(uint8_t** d, size_t* dl, char** s, size_t* sl,
1568         uint8_t* pkt, size_t pktlen)
1569 {
1570         uint8_t* od = *d;
1571         char* os = *s;
1572         size_t odl = *dl, osl = *sl;
1573         int w=sldns_wire2str_ipseckey_scan_internal(d, dl, s, sl, pkt, pktlen);
1574         if(w == -1) {
1575                 *d = od;
1576                 *s = os;
1577                 *dl = odl;
1578                 *sl = osl;
1579                 return -1;
1580         }
1581         return w;
1582 }
1583
1584 int sldns_wire2str_hip_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
1585 {
1586         int w;
1587         uint8_t algo, hitlen;
1588         uint16_t pklen;
1589
1590         /* read lengths */
1591         if(*dl < 4)
1592                 return -1;
1593         hitlen = (*d)[0];
1594         algo = (*d)[1];
1595         pklen = sldns_read_uint16((*d)+2);
1596         if(*dl < (size_t)4 + (size_t)hitlen + (size_t)pklen)
1597                 return -1;
1598
1599         /* write: algo hit pubkey */
1600         w = sldns_str_print(s, sl, "%u ", (unsigned)algo);
1601         w += print_hex_buf(s, sl, (*d)+4, hitlen);
1602         w += sldns_str_print(s, sl, " ");
1603         (*d)+=4+hitlen;
1604         (*dl)-= (4+hitlen);
1605         w += sldns_wire2str_b64_scan_num(d, dl, s, sl, pklen);
1606         return w;
1607 }
1608
1609 int sldns_wire2str_int16_data_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
1610 {
1611         int w;
1612         uint16_t n;
1613         if(*dl < 2)
1614                 return -1;
1615         n = sldns_read_uint16(*d);
1616         if(*dl < 2+(size_t)n)
1617                 return -1;
1618         (*d)+=2;
1619         (*dl)-=2;
1620         if(n == 0) {
1621                 return sldns_str_print(s, sl, "0");
1622         }
1623         w = sldns_str_print(s, sl, "%u ", (unsigned)n);
1624         w += sldns_wire2str_b64_scan_num(d, dl, s, sl, n);
1625         return w;
1626 }
1627
1628 int sldns_wire2str_nsec3_next_owner_scan(uint8_t** d, size_t* dl, char** s,
1629         size_t* sl)
1630 {
1631         return sldns_wire2str_b32_ext_scan(d, dl, s, sl);
1632 }
1633
1634 int sldns_wire2str_ilnp64_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
1635 {
1636         int w;
1637         if(*dl < 8)
1638                 return -1;
1639         w = sldns_str_print(s, sl, "%.4x:%.4x:%.4x:%.4x",
1640                 sldns_read_uint16(*d), sldns_read_uint16((*d)+2),
1641                 sldns_read_uint16((*d)+4), sldns_read_uint16((*d)+6));
1642         (*d)+=8;
1643         (*dl)-=8;
1644         return w;
1645 }
1646
1647 int sldns_wire2str_eui48_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
1648 {
1649         int w;
1650         if(*dl < 6)
1651                 return -1;
1652         w = sldns_str_print(s, sl, "%.2x-%.2x-%.2x-%.2x-%.2x-%.2x",
1653                 (*d)[0], (*d)[1], (*d)[2], (*d)[3], (*d)[4], (*d)[5]);
1654         (*d)+=6;
1655         (*dl)-=6;
1656         return w;
1657 }
1658
1659 int sldns_wire2str_eui64_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
1660 {
1661         int w;
1662         if(*dl < 8)
1663                 return -1;
1664         w = sldns_str_print(s, sl, "%.2x-%.2x-%.2x-%.2x-%.2x-%.2x-%.2x-%.2x",
1665                 (*d)[0], (*d)[1], (*d)[2], (*d)[3], (*d)[4], (*d)[5],
1666                 (*d)[6], (*d)[7]);
1667         (*d)+=8;
1668         (*dl)-=8;
1669         return w;
1670 }
1671
1672 int sldns_wire2str_tag_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
1673 {
1674         size_t i, n;
1675         int w = 0;
1676         if(*dl < 1)
1677                 return -1;
1678         n = (size_t)((*d)[0]);
1679         if(*dl < 1+n)
1680                 return -1;
1681         for(i=0; i<n; i++)
1682                 if(!isalnum((unsigned char)(*d)[i+1]))
1683                         return -1;
1684         for(i=0; i<n; i++)
1685                 w += sldns_str_print(s, sl, "%c", (char)(*d)[i+1]);
1686         (*d)+=n+1;
1687         (*dl)-=(n+1);
1688         return w;
1689 }
1690
1691 int sldns_wire2str_long_str_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
1692 {
1693         size_t i;
1694         int w = 0;
1695         w += sldns_str_print(s, sl, "\"");
1696         for(i=0; i<*dl; i++)
1697                 w += str_char_print(s, sl, (*d)[i]);
1698         w += sldns_str_print(s, sl, "\"");
1699         (*d)+=*dl;
1700         (*dl)=0;
1701         return w;
1702 }
1703
1704 int sldns_wire2str_tsigerror_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
1705 {
1706         sldns_lookup_table *lt;
1707         int data, w;
1708         if(*dl < 2) return -1;
1709         data = (int)sldns_read_uint16(*d);
1710         lt = sldns_lookup_by_id(sldns_tsig_errors, data);
1711         if(lt && lt->name)
1712                 w = sldns_str_print(s, sl, "%s", lt->name);
1713         else    w = sldns_str_print(s, sl, "%d", data);
1714         (*dl)-=2;
1715         (*d)+=2;
1716         return w;
1717 }
1718
1719 int sldns_wire2str_edns_llq_print(char** s, size_t* sl, uint8_t* data,
1720         size_t len)
1721 {
1722         /* LLQ constants */
1723         const char* llq_errors[] = {"NO-ERROR", "SERV-FULL", "STATIC",
1724                 "FORMAT-ERR", "NO-SUCH-LLQ", "BAD-VERS", "UNKNOWN_ERR"};
1725         const unsigned int llq_errors_num = 7;
1726         const char* llq_opcodes[] = {"LLQ-SETUP", "LLQ-REFRESH", "LLQ-EVENT"};
1727         const unsigned int llq_opcodes_num = 3;
1728         uint16_t version, llq_opcode, error_code;
1729         uint64_t llq_id;
1730         uint32_t lease_life; /* Requested or granted life of LLQ, in seconds */
1731         int w = 0;
1732
1733         /* read the record */
1734         if(len != 18) {
1735                 w += sldns_str_print(s, sl, "malformed LLQ ");
1736                 w += print_hex_buf(s, sl, data, len);
1737                 return w;
1738         }
1739         version = sldns_read_uint16(data);
1740         llq_opcode = sldns_read_uint16(data+2);
1741         error_code = sldns_read_uint16(data+4);
1742         memmove(&llq_id, data+6, sizeof(llq_id));
1743         lease_life = sldns_read_uint32(data+14);
1744
1745         /* print it */
1746         w += sldns_str_print(s, sl, "v%d ", (int)version);
1747         if(llq_opcode < llq_opcodes_num)
1748                 w += sldns_str_print(s, sl, "%s", llq_opcodes[llq_opcode]);
1749         else    w += sldns_str_print(s, sl, "opcode %d", (int)llq_opcode);
1750         if(error_code < llq_errors_num)
1751                 w += sldns_str_print(s, sl, " %s", llq_errors[error_code]);
1752         else    w += sldns_str_print(s, sl, " error %d", (int)error_code);
1753 #ifndef USE_WINSOCK
1754         w += sldns_str_print(s, sl, " id %llx lease-life %lu",
1755                 (unsigned long long)llq_id, (unsigned long)lease_life);
1756 #else
1757         w += sldns_str_print(s, sl, " id %I64x lease-life %lu",
1758                 (unsigned long long)llq_id, (unsigned long)lease_life);
1759 #endif
1760         return w;
1761 }
1762
1763 int sldns_wire2str_edns_ul_print(char** s, size_t* sl, uint8_t* data,
1764         size_t len)
1765 {
1766         uint32_t lease;
1767         int w = 0;
1768         if(len != 4) {
1769                 w += sldns_str_print(s, sl, "malformed UL ");
1770                 w += print_hex_buf(s, sl, data, len);
1771                 return w;
1772         }
1773         lease = sldns_read_uint32(data);
1774         w += sldns_str_print(s, sl, "lease %lu", (unsigned long)lease);
1775         return w;
1776 }
1777
1778 int sldns_wire2str_edns_nsid_print(char** s, size_t* sl, uint8_t* data,
1779         size_t len)
1780 {
1781         int w = 0;
1782         size_t i, printed=0;
1783         w += print_hex_buf(s, sl, data, len);
1784         for(i=0; i<len; i++) {
1785                 if(isprint((unsigned char)data[i]) || data[i] == '\t') {
1786                         if(!printed) {
1787                                 w += sldns_str_print(s, sl, " (");
1788                                 printed = 1;
1789                         }
1790                         w += sldns_str_print(s, sl, "%c", (char)data[i]);
1791                 }
1792         }
1793         if(printed)
1794                 w += sldns_str_print(s, sl, ")");
1795         return w;
1796 }
1797
1798 int sldns_wire2str_edns_dau_print(char** s, size_t* sl, uint8_t* data,
1799         size_t len)
1800 {
1801         sldns_lookup_table *lt;
1802         size_t i;
1803         int w = 0;
1804         for(i=0; i<len; i++) {
1805                 lt = sldns_lookup_by_id(sldns_algorithms, (int)data[i]);
1806                 if(lt && lt->name)
1807                         w += sldns_str_print(s, sl, " %s", lt->name);
1808                 else    w += sldns_str_print(s, sl, " %d", (int)data[i]);
1809         }
1810         return w;
1811 }
1812
1813 int sldns_wire2str_edns_dhu_print(char** s, size_t* sl, uint8_t* data,
1814         size_t len)
1815 {
1816         sldns_lookup_table *lt;
1817         size_t i;
1818         int w = 0;
1819         for(i=0; i<len; i++) {
1820                 lt = sldns_lookup_by_id(sldns_hashes, (int)data[i]);
1821                 if(lt && lt->name)
1822                         w += sldns_str_print(s, sl, " %s", lt->name);
1823                 else    w += sldns_str_print(s, sl, " %d", (int)data[i]);
1824         }
1825         return w;
1826 }
1827
1828 int sldns_wire2str_edns_n3u_print(char** s, size_t* sl, uint8_t* data,
1829         size_t len)
1830 {
1831         size_t i;
1832         int w = 0;
1833         for(i=0; i<len; i++) {
1834                 if(data[i] == 1)
1835                         w += sldns_str_print(s, sl, " SHA1");
1836                 else    w += sldns_str_print(s, sl, " %d", (int)data[i]);
1837         }
1838         return w;
1839 }
1840
1841 int sldns_wire2str_edns_subnet_print(char** s, size_t* sl, uint8_t* data,
1842         size_t len)
1843 {
1844         int w = 0;
1845         uint16_t family;
1846         uint8_t source, scope;
1847         if(len < 4) {
1848                 w += sldns_str_print(s, sl, "malformed subnet ");
1849                 w += print_hex_buf(s, sl, data, len);
1850                 return w;
1851         }
1852         family = sldns_read_uint16(data);
1853         source = data[2];
1854         scope = data[3];
1855         if(family == 1) {
1856                 /* IP4 */
1857                 char buf[64];
1858                 uint8_t ip4[4];
1859                 memset(ip4, 0, sizeof(ip4));
1860                 if(len-4 > 4) {
1861                         w += sldns_str_print(s, sl, "trailingdata:");
1862                         w += print_hex_buf(s, sl, data+4+4, len-4-4);
1863                         w += sldns_str_print(s, sl, " ");
1864                         len = 4+4;
1865                 }
1866                 memmove(ip4, data+4, len-4);
1867                 if(!inet_ntop(AF_INET, ip4, buf, (socklen_t)sizeof(buf))) {
1868                         w += sldns_str_print(s, sl, "ip4ntoperror ");
1869                         w += print_hex_buf(s, sl, data+4+4, len-4-4);
1870                 } else {
1871                         w += sldns_str_print(s, sl, "%s", buf);
1872                 }
1873         } else if(family == 2) {
1874                 /* IP6 */
1875                 char buf[64];
1876                 uint8_t ip6[16];
1877                 memset(ip6, 0, sizeof(ip6));
1878                 if(len-4 > 16) {
1879                         w += sldns_str_print(s, sl, "trailingdata:");
1880                         w += print_hex_buf(s, sl, data+4+16, len-4-16);
1881                         w += sldns_str_print(s, sl, " ");
1882                         len = 4+16;
1883                 }
1884                 memmove(ip6, data+4, len-4);
1885 #ifdef AF_INET6
1886                 if(!inet_ntop(AF_INET6, ip6, buf, (socklen_t)sizeof(buf))) {
1887                         w += sldns_str_print(s, sl, "ip6ntoperror ");
1888                         w += print_hex_buf(s, sl, data+4+4, len-4-4);
1889                 } else {
1890                         w += sldns_str_print(s, sl, "%s", buf);
1891                 }
1892 #else
1893                 w += print_hex_buf(s, sl, data+4+4, len-4-4);
1894 #endif
1895         } else {
1896                 /* unknown */
1897                 w += sldns_str_print(s, sl, "family %d ",
1898                         (int)family);
1899                 w += print_hex_buf(s, sl, data, len);
1900         }
1901         w += sldns_str_print(s, sl, "/%d scope /%d", (int)source, (int)scope);
1902         return w;
1903 }
1904
1905 static int sldns_wire2str_edns_keepalive_print(char** s, size_t* sl, uint8_t* data,
1906         size_t len)
1907 {
1908         int w = 0;
1909         uint16_t timeout;
1910         if(!(len == 0 || len == 2)) {
1911                 w += sldns_str_print(s, sl, "malformed keepalive ");
1912                 w += print_hex_buf(s, sl, data, len);
1913                 return w;
1914         }
1915         if(len == 0 ) {
1916                 w += sldns_str_print(s, sl, "no timeout value (only valid for client option) ");
1917         } else {
1918                 timeout = sldns_read_uint16(data);
1919                 w += sldns_str_print(s, sl, "timeout value in units of 100ms %u", (int)timeout);
1920         }
1921         return w;
1922 }
1923
1924 int sldns_wire2str_edns_option_print(char** s, size_t* sl,
1925         uint16_t option_code, uint8_t* optdata, size_t optlen)
1926 {
1927         int w = 0;
1928         w += sldns_wire2str_edns_option_code_print(s, sl, option_code);
1929         w += sldns_str_print(s, sl, ": ");
1930         switch(option_code) {
1931         case LDNS_EDNS_LLQ:
1932                 w += sldns_wire2str_edns_llq_print(s, sl, optdata, optlen);
1933                 break;
1934         case LDNS_EDNS_UL:
1935                 w += sldns_wire2str_edns_ul_print(s, sl, optdata, optlen);
1936                 break;
1937         case LDNS_EDNS_NSID:
1938                 w += sldns_wire2str_edns_nsid_print(s, sl, optdata, optlen);
1939                 break;
1940         case LDNS_EDNS_DAU:
1941                 w += sldns_wire2str_edns_dau_print(s, sl, optdata, optlen);
1942                 break;
1943         case LDNS_EDNS_DHU:
1944                 w += sldns_wire2str_edns_dhu_print(s, sl, optdata, optlen);
1945                 break;
1946         case LDNS_EDNS_N3U:
1947                 w += sldns_wire2str_edns_n3u_print(s, sl, optdata, optlen);
1948                 break;
1949         case LDNS_EDNS_CLIENT_SUBNET:
1950                 w += sldns_wire2str_edns_subnet_print(s, sl, optdata, optlen);
1951                 break;
1952          case LDNS_EDNS_KEEPALIVE:
1953                 w += sldns_wire2str_edns_keepalive_print(s, sl, optdata, optlen);
1954                 break;
1955         case LDNS_EDNS_PADDING:
1956                 w += print_hex_buf(s, sl, optdata, optlen);
1957                 break;
1958         default:
1959                 /* unknown option code */
1960                 w += print_hex_buf(s, sl, optdata, optlen);
1961                 break;
1962         }
1963         return w;
1964 }
1965
1966 /** print the edns options to string */
1967 static int
1968 print_edns_opts(char** s, size_t* sl, uint8_t* rdata, size_t rdatalen)
1969 {
1970         uint16_t option_code, option_len;
1971         int w = 0;
1972         while(rdatalen > 0) {
1973                 /* option name */
1974                 if(rdatalen < 4) {
1975                         w += sldns_str_print(s, sl, " ; malformed: ");
1976                         w += print_hex_buf(s, sl, rdata, rdatalen);
1977                         return w;
1978                 }
1979                 option_code = sldns_read_uint16(rdata);
1980                 option_len = sldns_read_uint16(rdata+2);
1981                 rdata += 4;
1982                 rdatalen -= 4;
1983
1984                 /* option value */
1985                 if(rdatalen < (size_t)option_len) {
1986                         w += sldns_str_print(s, sl, " ; malformed ");
1987                         w += sldns_wire2str_edns_option_code_print(s, sl,
1988                                 option_code);
1989                         w += sldns_str_print(s, sl, ": ");
1990                         w += print_hex_buf(s, sl, rdata, rdatalen);
1991                         return w;
1992                 }
1993                 w += sldns_str_print(s, sl, " ; ");
1994                 w += sldns_wire2str_edns_option_print(s, sl, option_code,
1995                         rdata, option_len);
1996                 rdata += option_len;
1997                 rdatalen -= option_len;
1998         }
1999         return w;
2000 }
2001
2002 int sldns_wire2str_edns_scan(uint8_t** data, size_t* data_len, char** str,
2003         size_t* str_len, uint8_t* pkt, size_t pktlen)
2004 {
2005         int w = 0;
2006         uint8_t ext_rcode, edns_version;
2007         uint16_t udpsize, edns_bits, rdatalen;
2008         w += sldns_str_print(str, str_len, "; EDNS:");
2009
2010         /* some input checks, domain name */
2011         if(*data_len < 1+10)
2012                 return w + print_remainder_hex("Error malformed 0x",
2013                         data, data_len, str, str_len);
2014         if(*data[0] != 0) {
2015                 return w + print_remainder_hex("Error nonrootdname 0x",
2016                         data, data_len, str, str_len);
2017         }
2018         (*data)++;
2019         (*data_len)--;
2020
2021         /* check type and read fixed contents */
2022         if(sldns_read_uint16((*data)) != LDNS_RR_TYPE_OPT) {
2023                 return w + print_remainder_hex("Error nottypeOPT 0x",
2024                         data, data_len, str, str_len);
2025         }
2026         udpsize = sldns_read_uint16((*data)+2);
2027         ext_rcode = (*data)[4];
2028         edns_version = (*data)[5];
2029         edns_bits = sldns_read_uint16((*data)+6);
2030         rdatalen = sldns_read_uint16((*data)+8);
2031         (*data)+=10;
2032         (*data_len)-=10;
2033
2034         w += sldns_str_print(str, str_len, " version: %u;",
2035                 (unsigned)edns_version);
2036         w += sldns_str_print(str, str_len, " flags:");
2037         if((edns_bits & LDNS_EDNS_MASK_DO_BIT))
2038                 w += sldns_str_print(str, str_len, " do");
2039         /* the extended rcode is the value set, shifted four bits,
2040          * and or'd with the original rcode */
2041         if(ext_rcode) {
2042                 int rc = ((int)ext_rcode)<<4;
2043                 if(pkt && pktlen >= LDNS_HEADER_SIZE)
2044                         rc |= LDNS_RCODE_WIRE(pkt);
2045                 w += sldns_str_print(str, str_len, " ; ext-rcode: %d", rc);
2046         }
2047         w += sldns_str_print(str, str_len, " ; udp: %u", (unsigned)udpsize);
2048
2049         if(rdatalen) {
2050                 if((size_t)*data_len < rdatalen) {
2051                         w += sldns_str_print(str, str_len,
2052                                 " ; Error EDNS rdata too short; ");
2053                         rdatalen = (uint16_t)*data_len;
2054                 }
2055                 w += print_edns_opts(str, str_len, *data, rdatalen);
2056                 (*data) += rdatalen;
2057                 (*data_len) -= rdatalen;
2058         }
2059         w += sldns_str_print(str, str_len, "\n");
2060         return w;
2061 }