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