]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/unbound/sldns/wire2str.c
Upgrade Unbound to 1.6.4. 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         return sldns_wire2str_b64_scan_num(d, dl, s, sl, *dl);
1224 }
1225
1226 int sldns_wire2str_hex_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
1227 {
1228         return print_remainder_hex("", d, dl, s, sl);
1229 }
1230
1231 int sldns_wire2str_nsec_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
1232 {
1233         uint8_t* p = *d;
1234         size_t pl = *dl;
1235         unsigned i, bit, window, block_len;
1236         uint16_t t;
1237         int w = 0;
1238         
1239         /* check for errors */
1240         while(pl) {
1241                 if(pl < 2) return -1;
1242                 block_len = (unsigned)p[1];
1243                 if(pl < 2+block_len) return -1;
1244                 p += block_len+2;
1245                 pl -= block_len+2;
1246         }
1247
1248         /* do it */
1249         p = *d;
1250         pl = *dl;
1251         while(pl) {
1252                 if(pl < 2) return -1; /* cannot happen */
1253                 window = (unsigned)p[0];
1254                 block_len = (unsigned)p[1];
1255                 if(pl < 2+block_len) return -1; /* cannot happen */
1256                 p += 2;
1257                 for(i=0; i<block_len; i++) {
1258                         if(p[i] == 0) continue;
1259                         /* base type number for this octet */
1260                         t = ((window)<<8) | (i << 3);
1261                         for(bit=0; bit<8; bit++) {
1262                                 if((p[i]&(0x80>>bit))) {
1263                                         if(w) w += sldns_str_print(s, sl, " ");
1264                                         w += sldns_wire2str_type_print(s, sl,
1265                                                 t+bit);
1266                                 }
1267                         }
1268                 }
1269                 p += block_len;
1270                 pl -= block_len+2;
1271         }
1272         (*d) += *dl;
1273         (*dl) = 0;
1274         return w;
1275 }
1276
1277 int sldns_wire2str_nsec3_salt_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
1278 {
1279         size_t salt_len;
1280         int w;
1281         if(*dl < 1) return -1;
1282         salt_len = (size_t)(*d)[0];
1283         if(*dl < 1+salt_len) return -1;
1284         (*d)++;
1285         (*dl)--;
1286         if(salt_len == 0) {
1287                 return sldns_str_print(s, sl, "-");
1288         }
1289         w = print_hex_buf(s, sl, *d, salt_len);
1290         (*dl)-=salt_len;
1291         (*d)+=salt_len;
1292         return w;
1293 }
1294
1295 int sldns_wire2str_cert_alg_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
1296 {
1297         sldns_lookup_table *lt;
1298         int data, w;
1299         if(*dl < 2) return -1;
1300         data = (int)sldns_read_uint16(*d);
1301         lt = sldns_lookup_by_id(sldns_cert_algorithms, data);
1302         if(lt && lt->name)
1303                 w = sldns_str_print(s, sl, "%s", lt->name);
1304         else    w = sldns_str_print(s, sl, "%d", data);
1305         (*dl)-=2;
1306         (*d)+=2;
1307         return w;
1308 }
1309
1310 int sldns_wire2str_alg_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
1311 {
1312         /* don't use algorithm mnemonics in the presentation format
1313          * this kind of got sneaked into the rfc's */
1314         return sldns_wire2str_int8_scan(d, dl, s, sl);
1315 }
1316
1317 int sldns_wire2str_unknown_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
1318 {
1319         return sldns_wire2str_rdata_unknown_scan(d, dl, s, sl);
1320 }
1321
1322 int sldns_wire2str_time_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
1323 {
1324         /* create a YYYYMMDDHHMMSS string if possible */
1325         struct tm tm;
1326         char date_buf[16];
1327         uint32_t t;
1328         memset(&tm, 0, sizeof(tm));
1329         if(*dl < 4) return -1;
1330         t = sldns_read_uint32(*d);
1331         date_buf[15]=0;
1332         if(sldns_serial_arithmitics_gmtime_r(t, time(NULL), &tm) &&
1333                 strftime(date_buf, 15, "%Y%m%d%H%M%S", &tm)) {
1334                 (*d) += 4;
1335                 (*dl) -= 4;
1336                 return sldns_str_print(s, sl, "%s", date_buf);
1337         }
1338         return -1;
1339 }
1340
1341 static int
1342 loc_cm_print(char** str, size_t* sl, uint8_t mantissa, uint8_t exponent)
1343 {
1344         int w = 0;
1345         uint8_t i;
1346         /* is it 0.<two digits> ? */
1347         if(exponent < 2) {
1348                 if(exponent == 1)
1349                         mantissa *= 10;
1350                 return sldns_str_print(str, sl, "0.%02ld", (long)mantissa);
1351         }
1352         /* always <digit><string of zeros> */
1353         w += sldns_str_print(str, sl, "%d", (int)mantissa);
1354         for(i=0; i<exponent-2; i++)
1355                 w += sldns_str_print(str, sl, "0");
1356         return w;
1357 }
1358
1359 int sldns_wire2str_loc_scan(uint8_t** d, size_t* dl, char** str, size_t* sl)
1360 {
1361         /* we could do checking (ie degrees < 90 etc)? */
1362         uint8_t version;
1363         uint8_t size;
1364         uint8_t horizontal_precision;
1365         uint8_t vertical_precision;
1366         uint32_t longitude;
1367         uint32_t latitude;
1368         uint32_t altitude;
1369         char northerness;
1370         char easterness;
1371         uint32_t h;
1372         uint32_t m;
1373         double s;
1374         uint32_t equator = (uint32_t)1 << 31; /* 2**31 */
1375         int w = 0;
1376
1377         if(*dl < 16) return -1;
1378         version = (*d)[0];
1379         if(version != 0)
1380                 return sldns_wire2str_hex_scan(d, dl, str, sl);
1381         size = (*d)[1];
1382         horizontal_precision = (*d)[2];
1383         vertical_precision = (*d)[3];
1384
1385         latitude = sldns_read_uint32((*d)+4);
1386         longitude = sldns_read_uint32((*d)+8);
1387         altitude = sldns_read_uint32((*d)+12);
1388
1389         if (latitude > equator) {
1390                 northerness = 'N';
1391                 latitude = latitude - equator;
1392         } else {
1393                 northerness = 'S';
1394                 latitude = equator - latitude;
1395         }
1396         h = latitude / (1000 * 60 * 60);
1397         latitude = latitude % (1000 * 60 * 60);
1398         m = latitude / (1000 * 60);
1399         latitude = latitude % (1000 * 60);
1400         s = (double) latitude / 1000.0;
1401         w += sldns_str_print(str, sl, "%02u %02u %06.3f %c ",
1402                 h, m, s, northerness);
1403
1404         if (longitude > equator) {
1405                 easterness = 'E';
1406                 longitude = longitude - equator;
1407         } else {
1408                 easterness = 'W';
1409                 longitude = equator - longitude;
1410         }
1411         h = longitude / (1000 * 60 * 60);
1412         longitude = longitude % (1000 * 60 * 60);
1413         m = longitude / (1000 * 60);
1414         longitude = longitude % (1000 * 60);
1415         s = (double) longitude / (1000.0);
1416         w += sldns_str_print(str, sl, "%02u %02u %06.3f %c ",
1417                 h, m, s, easterness);
1418
1419         s = ((double) altitude) / 100;
1420         s -= 100000;
1421
1422         if(altitude%100 != 0)
1423                 w += sldns_str_print(str, sl, "%.2f", s);
1424         else
1425                 w += sldns_str_print(str, sl, "%.0f", s);
1426
1427         w += sldns_str_print(str, sl, "m ");
1428
1429         w += loc_cm_print(str, sl, (size & 0xf0) >> 4, size & 0x0f);
1430         w += sldns_str_print(str, sl, "m ");
1431
1432         w += loc_cm_print(str, sl, (horizontal_precision & 0xf0) >> 4,
1433                 horizontal_precision & 0x0f);
1434         w += sldns_str_print(str, sl, "m ");
1435
1436         w += loc_cm_print(str, sl, (vertical_precision & 0xf0) >> 4,
1437                 vertical_precision & 0x0f);
1438         w += sldns_str_print(str, sl, "m");
1439
1440         (*d)+=16;
1441         (*dl)-=16;
1442         return w;
1443 }
1444
1445 int sldns_wire2str_wks_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
1446 {
1447         /* protocol, followed by bitmap of services */
1448         const char* proto_name = NULL;
1449         struct protoent *protocol;
1450         struct servent *service;
1451         uint8_t protocol_nr;
1452         int bit, port, w = 0;
1453         size_t i;
1454         /* we cannot print with strings because they
1455          * are not portable, the presentation format may
1456          * not be able to be read in on another computer.  */
1457         int print_symbols = 0;
1458
1459         /* protocol */
1460         if(*dl < 1) return -1;
1461         protocol_nr = (*d)[0];
1462         (*d)++;
1463         (*dl)--;
1464         protocol = getprotobynumber((int)protocol_nr);
1465         if(protocol && (protocol->p_name != NULL)) {
1466                 w += sldns_str_print(s, sl, "%s", protocol->p_name);
1467                 proto_name = protocol->p_name;
1468         } else  {
1469                 w += sldns_str_print(s, sl, "%u", (unsigned)protocol_nr);
1470         }
1471
1472         for(i=0; i<*dl; i++) {
1473                 if((*d)[i] == 0)
1474                         continue;
1475                 for(bit=0; bit<8; bit++) {
1476                         if(!(((*d)[i])&(0x80>>bit)))
1477                                 continue;
1478                         port = (int)i*8 + bit;
1479
1480                         if(!print_symbols)
1481                                 service = NULL;
1482                         else
1483                                 service = getservbyport(
1484                                         (int)htons((uint16_t)port), proto_name);
1485                         if(service && service->s_name)
1486                                 w += sldns_str_print(s, sl, " %s",
1487                                         service->s_name);
1488                         else    w += sldns_str_print(s, sl, " %u",
1489                                         (unsigned)port);
1490                 }
1491         }
1492
1493 #ifdef HAVE_ENDSERVENT
1494         endservent();
1495 #endif
1496 #ifdef HAVE_ENDPROTOENT
1497         endprotoent();
1498 #endif
1499         (*d) += *dl;
1500         (*dl) = 0;
1501         return w;
1502 }
1503
1504 int sldns_wire2str_nsap_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
1505 {
1506         return print_remainder_hex("0x", d, dl, s, sl);
1507 }
1508
1509 int sldns_wire2str_atma_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
1510 {
1511         return print_remainder_hex("", d, dl, s, sl);
1512 }
1513
1514 /* internal scan routine that can modify arguments on failure */
1515 static int sldns_wire2str_ipseckey_scan_internal(uint8_t** d, size_t* dl,
1516         char** s, size_t* sl, uint8_t* pkt, size_t pktlen)
1517 {
1518         /* http://www.ietf.org/internet-drafts/draft-ietf-ipseckey-rr-12.txt*/
1519         uint8_t precedence, gateway_type, algorithm;
1520         int w = 0;
1521
1522         if(*dl < 3) return -1;
1523         precedence = (*d)[0];
1524         gateway_type = (*d)[1];
1525         algorithm = (*d)[2];
1526         if(gateway_type > 3)
1527                 return -1; /* unknown */
1528         (*d)+=3;
1529         (*dl)-=3;
1530         w += sldns_str_print(s, sl, "%d %d %d ",
1531                 (int)precedence, (int)gateway_type, (int)algorithm);
1532
1533         switch(gateway_type) {
1534         case 0: /* no gateway */
1535                 w += sldns_str_print(s, sl, ".");
1536                 break;
1537         case 1: /* ip4 */
1538                 w += sldns_wire2str_a_scan(d, dl, s, sl);
1539                 break;
1540         case 2: /* ip6 */
1541                 w += sldns_wire2str_aaaa_scan(d, dl, s, sl);
1542                 break;
1543         case 3: /* dname */
1544                 w += sldns_wire2str_dname_scan(d, dl, s, sl, pkt, pktlen);
1545                 break;
1546         default: /* unknown */
1547                 return -1;
1548         }
1549
1550         if(*dl < 1)
1551                 return -1;
1552         w += sldns_str_print(s, sl, " ");
1553         w += sldns_wire2str_b64_scan_num(d, dl, s, sl, *dl);
1554         return w;
1555 }
1556
1557 int sldns_wire2str_ipseckey_scan(uint8_t** d, size_t* dl, char** s, size_t* sl,
1558         uint8_t* pkt, size_t pktlen)
1559 {
1560         uint8_t* od = *d;
1561         char* os = *s;
1562         size_t odl = *dl, osl = *sl;
1563         int w=sldns_wire2str_ipseckey_scan_internal(d, dl, s, sl, pkt, pktlen);
1564         if(w == -1) {
1565                 *d = od;
1566                 *s = os;
1567                 *dl = odl;
1568                 *sl = osl;
1569                 return -1;
1570         }
1571         return w;
1572 }
1573
1574 int sldns_wire2str_hip_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
1575 {
1576         int w;
1577         uint8_t algo, hitlen;
1578         uint16_t pklen;
1579
1580         /* read lengths */
1581         if(*dl < 4)
1582                 return -1;
1583         hitlen = (*d)[0];
1584         algo = (*d)[1];
1585         pklen = sldns_read_uint16((*d)+2);
1586         if(*dl < (size_t)4 + (size_t)hitlen + (size_t)pklen)
1587                 return -1;
1588
1589         /* write: algo hit pubkey */
1590         w = sldns_str_print(s, sl, "%u ", (unsigned)algo);
1591         w += print_hex_buf(s, sl, (*d)+4, hitlen);
1592         w += sldns_str_print(s, sl, " ");
1593         (*d)+=4+hitlen;
1594         (*dl)-= (4+hitlen);
1595         w += sldns_wire2str_b64_scan_num(d, dl, s, sl, pklen);
1596         return w;
1597 }
1598
1599 int sldns_wire2str_int16_data_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
1600 {
1601         int w;
1602         uint16_t n;
1603         if(*dl < 2)
1604                 return -1;
1605         n = sldns_read_uint16(*d);
1606         if(*dl < 2+(size_t)n)
1607                 return -1;
1608         (*d)+=2;
1609         (*dl)-=2;
1610         if(n == 0) {
1611                 return sldns_str_print(s, sl, "0");
1612         }
1613         w = sldns_str_print(s, sl, "%u ", (unsigned)n);
1614         w += sldns_wire2str_b64_scan_num(d, dl, s, sl, n);
1615         return w;
1616 }
1617
1618 int sldns_wire2str_nsec3_next_owner_scan(uint8_t** d, size_t* dl, char** s,
1619         size_t* sl)
1620 {
1621         return sldns_wire2str_b32_ext_scan(d, dl, s, sl);
1622 }
1623
1624 int sldns_wire2str_ilnp64_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
1625 {
1626         int w;
1627         if(*dl < 8)
1628                 return -1;
1629         w = sldns_str_print(s, sl, "%.4x:%.4x:%.4x:%.4x",
1630                 sldns_read_uint16(*d), sldns_read_uint16((*d)+2),
1631                 sldns_read_uint16((*d)+4), sldns_read_uint16((*d)+6));
1632         (*d)+=8;
1633         (*dl)-=8;
1634         return w;
1635 }
1636
1637 int sldns_wire2str_eui48_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
1638 {
1639         int w;
1640         if(*dl < 6)
1641                 return -1;
1642         w = sldns_str_print(s, sl, "%.2x-%.2x-%.2x-%.2x-%.2x-%.2x",
1643                 (*d)[0], (*d)[1], (*d)[2], (*d)[3], (*d)[4], (*d)[5]);
1644         (*d)+=6;
1645         (*dl)-=6;
1646         return w;
1647 }
1648
1649 int sldns_wire2str_eui64_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
1650 {
1651         int w;
1652         if(*dl < 8)
1653                 return -1;
1654         w = sldns_str_print(s, sl, "%.2x-%.2x-%.2x-%.2x-%.2x-%.2x-%.2x-%.2x",
1655                 (*d)[0], (*d)[1], (*d)[2], (*d)[3], (*d)[4], (*d)[5],
1656                 (*d)[6], (*d)[7]);
1657         (*d)+=8;
1658         (*dl)-=8;
1659         return w;
1660 }
1661
1662 int sldns_wire2str_tag_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
1663 {
1664         size_t i, n;
1665         int w = 0;
1666         if(*dl < 1)
1667                 return -1;
1668         n = (size_t)((*d)[0]);
1669         if(*dl < 1+n)
1670                 return -1;
1671         for(i=0; i<n; i++)
1672                 if(!isalnum((unsigned char)(*d)[i+1]))
1673                         return -1;
1674         for(i=0; i<n; i++)
1675                 w += sldns_str_print(s, sl, "%c", (char)(*d)[i+1]);
1676         (*d)+=n+1;
1677         (*dl)-=(n+1);
1678         return w;
1679 }
1680
1681 int sldns_wire2str_long_str_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
1682 {
1683         size_t i;
1684         int w = 0;
1685         w += sldns_str_print(s, sl, "\"");
1686         for(i=0; i<*dl; i++)
1687                 w += str_char_print(s, sl, (*d)[i]);
1688         w += sldns_str_print(s, sl, "\"");
1689         (*d)+=*dl;
1690         (*dl)=0;
1691         return w;
1692 }
1693
1694 int sldns_wire2str_tsigerror_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
1695 {
1696         sldns_lookup_table *lt;
1697         int data, w;
1698         if(*dl < 2) return -1;
1699         data = (int)sldns_read_uint16(*d);
1700         lt = sldns_lookup_by_id(sldns_tsig_errors, data);
1701         if(lt && lt->name)
1702                 w = sldns_str_print(s, sl, "%s", lt->name);
1703         else    w = sldns_str_print(s, sl, "%d", data);
1704         (*dl)-=2;
1705         (*d)+=2;
1706         return w;
1707 }
1708
1709 int sldns_wire2str_edns_llq_print(char** s, size_t* sl, uint8_t* data,
1710         size_t len)
1711 {
1712         /* LLQ constants */
1713         const char* llq_errors[] = {"NO-ERROR", "SERV-FULL", "STATIC",
1714                 "FORMAT-ERR", "NO-SUCH-LLQ", "BAD-VERS", "UNKNOWN_ERR"};
1715         const unsigned int llq_errors_num = 7;
1716         const char* llq_opcodes[] = {"LLQ-SETUP", "LLQ-REFRESH", "LLQ-EVENT"};
1717         const unsigned int llq_opcodes_num = 3;
1718         uint16_t version, llq_opcode, error_code;
1719         uint64_t llq_id;
1720         uint32_t lease_life; /* Requested or granted life of LLQ, in seconds */
1721         int w = 0;
1722
1723         /* read the record */
1724         if(len != 18) {
1725                 w += sldns_str_print(s, sl, "malformed LLQ ");
1726                 w += print_hex_buf(s, sl, data, len);
1727                 return w;
1728         }
1729         version = sldns_read_uint16(data);
1730         llq_opcode = sldns_read_uint16(data+2);
1731         error_code = sldns_read_uint16(data+4);
1732         memmove(&llq_id, data+6, sizeof(llq_id));
1733         lease_life = sldns_read_uint32(data+14);
1734
1735         /* print it */
1736         w += sldns_str_print(s, sl, "v%d ", (int)version);
1737         if(llq_opcode < llq_opcodes_num)
1738                 w += sldns_str_print(s, sl, "%s", llq_opcodes[llq_opcode]);
1739         else    w += sldns_str_print(s, sl, "opcode %d", (int)llq_opcode);
1740         if(error_code < llq_errors_num)
1741                 w += sldns_str_print(s, sl, " %s", llq_errors[error_code]);
1742         else    w += sldns_str_print(s, sl, " error %d", (int)error_code);
1743 #ifndef USE_WINSOCK
1744         w += sldns_str_print(s, sl, " id %llx lease-life %lu",
1745                 (unsigned long long)llq_id, (unsigned long)lease_life);
1746 #else
1747         w += sldns_str_print(s, sl, " id %I64x lease-life %lu",
1748                 (unsigned long long)llq_id, (unsigned long)lease_life);
1749 #endif
1750         return w;
1751 }
1752
1753 int sldns_wire2str_edns_ul_print(char** s, size_t* sl, uint8_t* data,
1754         size_t len)
1755 {
1756         uint32_t lease;
1757         int w = 0;
1758         if(len != 4) {
1759                 w += sldns_str_print(s, sl, "malformed UL ");
1760                 w += print_hex_buf(s, sl, data, len);
1761                 return w;
1762         }
1763         lease = sldns_read_uint32(data);
1764         w += sldns_str_print(s, sl, "lease %lu", (unsigned long)lease);
1765         return w;
1766 }
1767
1768 int sldns_wire2str_edns_nsid_print(char** s, size_t* sl, uint8_t* data,
1769         size_t len)
1770 {
1771         int w = 0;
1772         size_t i, printed=0;
1773         w += print_hex_buf(s, sl, data, len);
1774         for(i=0; i<len; i++) {
1775                 if(isprint((unsigned char)data[i]) || data[i] == '\t') {
1776                         if(!printed) {
1777                                 w += sldns_str_print(s, sl, " (");
1778                                 printed = 1;
1779                         }
1780                         w += sldns_str_print(s, sl, "%c", (char)data[i]);
1781                 }
1782         }
1783         if(printed)
1784                 w += sldns_str_print(s, sl, ")");
1785         return w;
1786 }
1787
1788 int sldns_wire2str_edns_dau_print(char** s, size_t* sl, uint8_t* data,
1789         size_t len)
1790 {
1791         sldns_lookup_table *lt;
1792         size_t i;
1793         int w = 0;
1794         for(i=0; i<len; i++) {
1795                 lt = sldns_lookup_by_id(sldns_algorithms, (int)data[i]);
1796                 if(lt && lt->name)
1797                         w += sldns_str_print(s, sl, " %s", lt->name);
1798                 else    w += sldns_str_print(s, sl, " %d", (int)data[i]);
1799         }
1800         return w;
1801 }
1802
1803 int sldns_wire2str_edns_dhu_print(char** s, size_t* sl, uint8_t* data,
1804         size_t len)
1805 {
1806         sldns_lookup_table *lt;
1807         size_t i;
1808         int w = 0;
1809         for(i=0; i<len; i++) {
1810                 lt = sldns_lookup_by_id(sldns_hashes, (int)data[i]);
1811                 if(lt && lt->name)
1812                         w += sldns_str_print(s, sl, " %s", lt->name);
1813                 else    w += sldns_str_print(s, sl, " %d", (int)data[i]);
1814         }
1815         return w;
1816 }
1817
1818 int sldns_wire2str_edns_n3u_print(char** s, size_t* sl, uint8_t* data,
1819         size_t len)
1820 {
1821         size_t i;
1822         int w = 0;
1823         for(i=0; i<len; i++) {
1824                 if(data[i] == 1)
1825                         w += sldns_str_print(s, sl, " SHA1");
1826                 else    w += sldns_str_print(s, sl, " %d", (int)data[i]);
1827         }
1828         return w;
1829 }
1830
1831 int sldns_wire2str_edns_subnet_print(char** s, size_t* sl, uint8_t* data,
1832         size_t len)
1833 {
1834         int w = 0;
1835         uint16_t family;
1836         uint8_t source, scope;
1837         if(len < 4) {
1838                 w += sldns_str_print(s, sl, "malformed subnet ");
1839                 w += print_hex_buf(s, sl, data, len);
1840                 return w;
1841         }
1842         family = sldns_read_uint16(data);
1843         source = data[2];
1844         scope = data[3];
1845         if(family == 1) {
1846                 /* IP4 */
1847                 char buf[64];
1848                 uint8_t ip4[4];
1849                 memset(ip4, 0, sizeof(ip4));
1850                 if(len-4 > 4) {
1851                         w += sldns_str_print(s, sl, "trailingdata:");
1852                         w += print_hex_buf(s, sl, data+4+4, len-4-4);
1853                         w += sldns_str_print(s, sl, " ");
1854                         len = 4+4;
1855                 }
1856                 memmove(ip4, data+4, len-4);
1857                 if(!inet_ntop(AF_INET, ip4, buf, (socklen_t)sizeof(buf))) {
1858                         w += sldns_str_print(s, sl, "ip4ntoperror ");
1859                         w += print_hex_buf(s, sl, data+4+4, len-4-4);
1860                 } else {
1861                         w += sldns_str_print(s, sl, "%s", buf);
1862                 }
1863         } else if(family == 2) {
1864                 /* IP6 */
1865                 char buf[64];
1866                 uint8_t ip6[16];
1867                 memset(ip6, 0, sizeof(ip6));
1868                 if(len-4 > 16) {
1869                         w += sldns_str_print(s, sl, "trailingdata:");
1870                         w += print_hex_buf(s, sl, data+4+16, len-4-16);
1871                         w += sldns_str_print(s, sl, " ");
1872                         len = 4+16;
1873                 }
1874                 memmove(ip6, data+4, len-4);
1875 #ifdef AF_INET6
1876                 if(!inet_ntop(AF_INET6, ip6, buf, (socklen_t)sizeof(buf))) {
1877                         w += sldns_str_print(s, sl, "ip6ntoperror ");
1878                         w += print_hex_buf(s, sl, data+4+4, len-4-4);
1879                 } else {
1880                         w += sldns_str_print(s, sl, "%s", buf);
1881                 }
1882 #else
1883                 w += print_hex_buf(s, sl, data+4+4, len-4-4);
1884 #endif
1885         } else {
1886                 /* unknown */
1887                 w += sldns_str_print(s, sl, "family %d ",
1888                         (int)family);
1889                 w += print_hex_buf(s, sl, data, len);
1890         }
1891         w += sldns_str_print(s, sl, "/%d scope /%d", (int)source, (int)scope);
1892         return w;
1893 }
1894
1895 static int sldns_wire2str_edns_keepalive_print(char** s, size_t* sl, uint8_t* data,
1896         size_t len)
1897 {
1898         int w = 0;
1899         uint16_t timeout;
1900         if(!(len == 0 || len == 2)) {
1901                 w += sldns_str_print(s, sl, "malformed keepalive ");
1902                 w += print_hex_buf(s, sl, data, len);
1903                 return w;
1904         }
1905         if(len == 0 ) {
1906                 w += sldns_str_print(s, sl, "no timeout value (only valid for client option) ");
1907         } else {
1908                 timeout = sldns_read_uint16(data);
1909                 w += sldns_str_print(s, sl, "timeout value in units of 100ms %u", (int)timeout);
1910         }
1911         return w;
1912 }
1913
1914 int sldns_wire2str_edns_option_print(char** s, size_t* sl,
1915         uint16_t option_code, uint8_t* optdata, size_t optlen)
1916 {
1917         int w = 0;
1918         w += sldns_wire2str_edns_option_code_print(s, sl, option_code);
1919         w += sldns_str_print(s, sl, ": ");
1920         switch(option_code) {
1921         case LDNS_EDNS_LLQ:
1922                 w += sldns_wire2str_edns_llq_print(s, sl, optdata, optlen);
1923                 break;
1924         case LDNS_EDNS_UL:
1925                 w += sldns_wire2str_edns_ul_print(s, sl, optdata, optlen);
1926                 break;
1927         case LDNS_EDNS_NSID:
1928                 w += sldns_wire2str_edns_nsid_print(s, sl, optdata, optlen);
1929                 break;
1930         case LDNS_EDNS_DAU:
1931                 w += sldns_wire2str_edns_dau_print(s, sl, optdata, optlen);
1932                 break;
1933         case LDNS_EDNS_DHU:
1934                 w += sldns_wire2str_edns_dhu_print(s, sl, optdata, optlen);
1935                 break;
1936         case LDNS_EDNS_N3U:
1937                 w += sldns_wire2str_edns_n3u_print(s, sl, optdata, optlen);
1938                 break;
1939         case LDNS_EDNS_CLIENT_SUBNET:
1940                 w += sldns_wire2str_edns_subnet_print(s, sl, optdata, optlen);
1941                 break;
1942          case LDNS_EDNS_KEEPALIVE:
1943                 w += sldns_wire2str_edns_keepalive_print(s, sl, optdata, optlen);
1944                 break;
1945         case LDNS_EDNS_PADDING:
1946                 w += print_hex_buf(s, sl, optdata, optlen);
1947                 break;
1948         default:
1949                 /* unknown option code */
1950                 w += print_hex_buf(s, sl, optdata, optlen);
1951                 break;
1952         }
1953         return w;
1954 }
1955
1956 /** print the edns options to string */
1957 static int
1958 print_edns_opts(char** s, size_t* sl, uint8_t* rdata, size_t rdatalen)
1959 {
1960         uint16_t option_code, option_len;
1961         int w = 0;
1962         while(rdatalen > 0) {
1963                 /* option name */
1964                 if(rdatalen < 4) {
1965                         w += sldns_str_print(s, sl, " ; malformed: ");
1966                         w += print_hex_buf(s, sl, rdata, rdatalen);
1967                         return w;
1968                 }
1969                 option_code = sldns_read_uint16(rdata);
1970                 option_len = sldns_read_uint16(rdata+2);
1971                 rdata += 4;
1972                 rdatalen -= 4;
1973
1974                 /* option value */
1975                 if(rdatalen < (size_t)option_len) {
1976                         w += sldns_str_print(s, sl, " ; malformed ");
1977                         w += sldns_wire2str_edns_option_code_print(s, sl,
1978                                 option_code);
1979                         w += sldns_str_print(s, sl, ": ");
1980                         w += print_hex_buf(s, sl, rdata, rdatalen);
1981                         return w;
1982                 }
1983                 w += sldns_str_print(s, sl, " ; ");
1984                 w += sldns_wire2str_edns_option_print(s, sl, option_code,
1985                         rdata, option_len);
1986                 rdata += option_len;
1987                 rdatalen -= option_len;
1988         }
1989         return w;
1990 }
1991
1992 int sldns_wire2str_edns_scan(uint8_t** data, size_t* data_len, char** str,
1993         size_t* str_len, uint8_t* pkt, size_t pktlen)
1994 {
1995         int w = 0;
1996         uint8_t ext_rcode, edns_version;
1997         uint16_t udpsize, edns_bits, rdatalen;
1998         w += sldns_str_print(str, str_len, "; EDNS:");
1999
2000         /* some input checks, domain name */
2001         if(*data_len < 1+10)
2002                 return w + print_remainder_hex("Error malformed 0x",
2003                         data, data_len, str, str_len);
2004         if(*data[0] != 0) {
2005                 return w + print_remainder_hex("Error nonrootdname 0x",
2006                         data, data_len, str, str_len);
2007         }
2008         (*data)++;
2009         (*data_len)--;
2010
2011         /* check type and read fixed contents */
2012         if(sldns_read_uint16((*data)) != LDNS_RR_TYPE_OPT) {
2013                 return w + print_remainder_hex("Error nottypeOPT 0x",
2014                         data, data_len, str, str_len);
2015         }
2016         udpsize = sldns_read_uint16((*data)+2);
2017         ext_rcode = (*data)[4];
2018         edns_version = (*data)[5];
2019         edns_bits = sldns_read_uint16((*data)+6);
2020         rdatalen = sldns_read_uint16((*data)+8);
2021         (*data)+=10;
2022         (*data_len)-=10;
2023
2024         w += sldns_str_print(str, str_len, " version: %u;",
2025                 (unsigned)edns_version);
2026         w += sldns_str_print(str, str_len, " flags:");
2027         if((edns_bits & LDNS_EDNS_MASK_DO_BIT))
2028                 w += sldns_str_print(str, str_len, " do");
2029         /* the extended rcode is the value set, shifted four bits,
2030          * and or'd with the original rcode */
2031         if(ext_rcode) {
2032                 int rc = ((int)ext_rcode)<<4;
2033                 if(pkt && pktlen >= LDNS_HEADER_SIZE)
2034                         rc |= LDNS_RCODE_WIRE(pkt);
2035                 w += sldns_str_print(str, str_len, " ; ext-rcode: %d", rc);
2036         }
2037         w += sldns_str_print(str, str_len, " ; udp: %u", (unsigned)udpsize);
2038
2039         if(rdatalen) {
2040                 if((size_t)*data_len < rdatalen) {
2041                         w += sldns_str_print(str, str_len,
2042                                 " ; Error EDNS rdata too short; ");
2043                         rdatalen = (uint16_t)*data_len;
2044                 }
2045                 w += print_edns_opts(str, str_len, *data, rdatalen);
2046                 (*data) += rdatalen;
2047                 (*data_len) -= rdatalen;
2048         }
2049         w += sldns_str_print(str, str_len, "\n");
2050         return w;
2051 }