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