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