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