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