4 * conversion routines from the wire format
5 * to the presentation format (strings)
7 * (c) NLnet Labs, 2004-2006
9 * See the file LICENSE for the license
14 * Contains functions to translate the wireformat to text
15 * representation, as well as functions to print them.
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"
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" },
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" },
58 sldns_lookup_table* sldns_algorithms = sldns_algorithms_data;
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" },
68 sldns_lookup_table* sldns_hashes = sldns_hashes_data;
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" },
84 sldns_lookup_table* sldns_cert_algorithms = sldns_cert_algorithms_data;
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" },
101 sldns_lookup_table* sldns_rcodes = sldns_rcodes_data;
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" },
111 sldns_lookup_table* sldns_opcodes = sldns_opcodes_data;
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" },
178 sldns_lookup_table* sldns_wireparse_errors = sldns_wireparse_errors_data;
180 static sldns_lookup_table sldns_edns_flags_data[] = {
184 sldns_lookup_table* sldns_edns_flags = sldns_edns_flags_data;
186 static sldns_lookup_table sldns_edns_options_data[] = {
190 /* 4 draft-cheshire-edns0-owner-option */
194 { 8, "edns-client-subnet" },
196 { 11, "edns-tcp-keepalive"},
201 sldns_lookup_table* sldns_edns_options = sldns_edns_options_data;
203 /* From RFC8914 5.2 Table 3, the "Extended DNS Error Codes" registry. */
204 static sldns_lookup_table sldns_edns_ede_codes_data[] = {
205 { LDNS_EDE_NONE, "None" },
206 { LDNS_EDE_OTHER, "Other Error" },
207 { LDNS_EDE_UNSUPPORTED_DNSKEY_ALG, "Unsupported DNSKEY Algorithm" },
208 { LDNS_EDE_UNSUPPORTED_DS_DIGEST, "Unsupported DS Digest Type" },
209 { LDNS_EDE_STALE_ANSWER, "Stale Answer" },
210 { LDNS_EDE_FORGED_ANSWER, "Forged Answer" },
211 { LDNS_EDE_DNSSEC_INDETERMINATE, "DNSSEC Indeterminate" },
212 { LDNS_EDE_DNSSEC_BOGUS, "DNSSEC Bogus" },
213 { LDNS_EDE_SIGNATURE_EXPIRED, "Signature Expired" },
214 { LDNS_EDE_SIGNATURE_NOT_YET_VALID, "Signature Not Yet Valid" },
215 { LDNS_EDE_DNSKEY_MISSING, "DNSKEY Missing" },
216 { LDNS_EDE_RRSIGS_MISSING, "RRSIGs Missing" },
217 { LDNS_EDE_NO_ZONE_KEY_BIT_SET, "No Zone Key Bit Set" },
218 { LDNS_EDE_NSEC_MISSING, "NSEC Missing" },
219 { LDNS_EDE_CACHED_ERROR, "Cached Error" },
220 { LDNS_EDE_NOT_READY, "Not Ready" },
221 { LDNS_EDE_BLOCKED, "Blocked" },
222 { LDNS_EDE_CENSORED, "Censored" },
223 { LDNS_EDE_FILTERED, "Filtered" },
224 { LDNS_EDE_PROHIBITED, "Prohibited" },
225 { LDNS_EDE_STALE_NXDOMAIN_ANSWER, "Stale NXDOMAIN Answer" },
226 { LDNS_EDE_NOT_AUTHORITATIVE, "Not Authoritative" },
227 { LDNS_EDE_NOT_SUPPORTED, "Not Supported" },
228 { LDNS_EDE_NO_REACHABLE_AUTHORITY, "No Reachable Authority" },
229 { LDNS_EDE_NETWORK_ERROR, "Network Error" },
230 { LDNS_EDE_INVALID_DATA, "Invalid Data" },
233 sldns_lookup_table* sldns_edns_ede_codes = sldns_edns_ede_codes_data;
235 static sldns_lookup_table sldns_tsig_errors_data[] = {
236 { LDNS_TSIG_ERROR_NOERROR, "NOERROR" },
237 { LDNS_RCODE_FORMERR, "FORMERR" },
238 { LDNS_RCODE_SERVFAIL, "SERVFAIL" },
239 { LDNS_RCODE_NXDOMAIN, "NXDOMAIN" },
240 { LDNS_RCODE_NOTIMPL, "NOTIMPL" },
241 { LDNS_RCODE_REFUSED, "REFUSED" },
242 { LDNS_RCODE_YXDOMAIN, "YXDOMAIN" },
243 { LDNS_RCODE_YXRRSET, "YXRRSET" },
244 { LDNS_RCODE_NXRRSET, "NXRRSET" },
245 { LDNS_RCODE_NOTAUTH, "NOTAUTH" },
246 { LDNS_RCODE_NOTZONE, "NOTZONE" },
247 { LDNS_TSIG_ERROR_BADSIG, "BADSIG" },
248 { LDNS_TSIG_ERROR_BADKEY, "BADKEY" },
249 { LDNS_TSIG_ERROR_BADTIME, "BADTIME" },
250 { LDNS_TSIG_ERROR_BADMODE, "BADMODE" },
251 { LDNS_TSIG_ERROR_BADNAME, "BADNAME" },
252 { LDNS_TSIG_ERROR_BADALG, "BADALG" },
255 sldns_lookup_table* sldns_tsig_errors = sldns_tsig_errors_data;
257 /* draft-ietf-dnsop-svcb-https-06: 6. Initial SvcParamKeys */
258 const char *svcparamkey_strs[] = {
259 "mandatory", "alpn", "no-default-alpn", "port",
260 "ipv4hint", "ech", "ipv6hint", "dohpath"
263 char* sldns_wire2str_pkt(uint8_t* data, size_t len)
265 size_t slen = (size_t)sldns_wire2str_pkt_buf(data, len, NULL, 0);
266 char* result = (char*)malloc(slen+1);
267 if(!result) return NULL;
268 sldns_wire2str_pkt_buf(data, len, result, slen+1);
272 char* sldns_wire2str_rr(uint8_t* rr, size_t len)
274 size_t slen = (size_t)sldns_wire2str_rr_buf(rr, len, NULL, 0);
275 char* result = (char*)malloc(slen+1);
276 if(!result) return NULL;
277 sldns_wire2str_rr_buf(rr, len, result, slen+1);
281 char* sldns_wire2str_type(uint16_t rrtype)
284 sldns_wire2str_type_buf(rrtype, buf, sizeof(buf));
288 char* sldns_wire2str_class(uint16_t rrclass)
291 sldns_wire2str_class_buf(rrclass, buf, sizeof(buf));
295 char* sldns_wire2str_dname(uint8_t* dname, size_t dname_len)
297 size_t slen=(size_t)sldns_wire2str_dname_buf(dname, dname_len, NULL, 0);
298 char* result = (char*)malloc(slen+1);
299 if(!result) return NULL;
300 sldns_wire2str_dname_buf(dname, dname_len, result, slen+1);
304 char* sldns_wire2str_rcode(int rcode)
307 sldns_wire2str_rcode_buf(rcode, buf, sizeof(buf));
311 int sldns_wire2str_pkt_buf(uint8_t* d, size_t dlen, char* s, size_t slen)
313 /* use arguments as temporary variables */
314 return sldns_wire2str_pkt_scan(&d, &dlen, &s, &slen);
317 int sldns_wire2str_rr_buf(uint8_t* d, size_t dlen, char* s, size_t slen)
319 /* use arguments as temporary variables */
320 return sldns_wire2str_rr_scan(&d, &dlen, &s, &slen, NULL, 0, NULL);
323 int sldns_wire2str_rrquestion_buf(uint8_t* d, size_t dlen, char* s, size_t slen)
325 /* use arguments as temporary variables */
326 return sldns_wire2str_rrquestion_scan(&d, &dlen, &s, &slen, NULL, 0, NULL);
329 int sldns_wire2str_rdata_buf(uint8_t* rdata, size_t rdata_len, char* str,
330 size_t str_len, uint16_t rrtype)
332 /* use arguments as temporary variables */
333 return sldns_wire2str_rdata_scan(&rdata, &rdata_len, &str, &str_len,
334 rrtype, NULL, 0, NULL);
337 int sldns_wire2str_rr_unknown_buf(uint8_t* d, size_t dlen, char* s, size_t slen)
339 /* use arguments as temporary variables */
340 return sldns_wire2str_rr_unknown_scan(&d, &dlen, &s, &slen, NULL, 0, NULL);
343 int sldns_wire2str_rr_comment_buf(uint8_t* rr, size_t rrlen, size_t dname_len,
344 char* s, size_t slen)
346 uint16_t rrtype = sldns_wirerr_get_type(rr, rrlen, dname_len);
347 return sldns_wire2str_rr_comment_print(&s, &slen, rr, rrlen, dname_len,
351 int sldns_wire2str_type_buf(uint16_t rrtype, char* s, size_t slen)
353 /* use arguments as temporary variables */
354 return sldns_wire2str_type_print(&s, &slen, rrtype);
357 int sldns_wire2str_class_buf(uint16_t rrclass, char* s, size_t slen)
359 /* use arguments as temporary variables */
360 return sldns_wire2str_class_print(&s, &slen, rrclass);
363 int sldns_wire2str_rcode_buf(int rcode, char* s, size_t slen)
365 /* use arguments as temporary variables */
366 return sldns_wire2str_rcode_print(&s, &slen, rcode);
369 int sldns_wire2str_opcode_buf(int opcode, char* s, size_t slen)
371 /* use arguments as temporary variables */
372 return sldns_wire2str_opcode_print(&s, &slen, opcode);
375 int sldns_wire2str_dname_buf(uint8_t* d, size_t dlen, char* s, size_t slen)
377 /* use arguments as temporary variables */
378 return sldns_wire2str_dname_scan(&d, &dlen, &s, &slen, NULL, 0, NULL);
381 int sldns_str_vprint(char** str, size_t* slen, const char* format, va_list args)
383 int w = vsnprintf(*str, *slen, format, args);
385 /* error in printout */
387 } else if((size_t)w >= *slen) {
388 *str = NULL; /* we do not want str to point outside of buffer*/
397 int sldns_str_print(char** str, size_t* slen, const char* format, ...)
401 va_start(args, format);
402 w = sldns_str_vprint(str, slen, format, args);
407 /** print hex format into text buffer for specified length */
408 static int print_hex_buf(char** s, size_t* slen, uint8_t* buf, size_t len)
410 const char* hex = "0123456789ABCDEF";
412 for(i=0; i<len; i++) {
413 (void)sldns_str_print(s, slen, "%c%c", hex[(buf[i]&0xf0)>>4],
419 /** print remainder of buffer in hex format with prefixed text */
420 static int print_remainder_hex(const char* pref, uint8_t** d, size_t* dlen,
421 char** s, size_t* slen)
424 w += sldns_str_print(s, slen, "%s", pref);
425 w += print_hex_buf(s, slen, *d, *dlen);
431 int sldns_wire2str_pkt_scan(uint8_t** d, size_t* dlen, char** s, size_t* slen)
433 int w = 0, comprloop = 0;
434 unsigned qdcount, ancount, nscount, arcount, i;
436 size_t pktlen = *dlen;
437 if(*dlen >= LDNS_HEADER_SIZE) {
438 qdcount = (unsigned)LDNS_QDCOUNT(*d);
439 ancount = (unsigned)LDNS_ANCOUNT(*d);
440 nscount = (unsigned)LDNS_NSCOUNT(*d);
441 arcount = (unsigned)LDNS_ARCOUNT(*d);
443 qdcount = ancount = nscount = arcount = 0;
445 w += sldns_wire2str_header_scan(d, dlen, s, slen);
446 w += sldns_str_print(s, slen, "\n");
447 w += sldns_str_print(s, slen, ";; QUESTION SECTION:\n");
448 for(i=0; i<qdcount; i++) {
449 w += sldns_wire2str_rrquestion_scan(d, dlen, s, slen,
450 pkt, pktlen, &comprloop);
453 w += sldns_str_print(s, slen, "\n");
454 w += sldns_str_print(s, slen, ";; ANSWER SECTION:\n");
455 for(i=0; i<ancount; i++) {
456 w += sldns_wire2str_rr_scan(d, dlen, s, slen, pkt, pktlen, &comprloop);
459 w += sldns_str_print(s, slen, "\n");
460 w += sldns_str_print(s, slen, ";; AUTHORITY SECTION:\n");
461 for(i=0; i<nscount; i++) {
462 w += sldns_wire2str_rr_scan(d, dlen, s, slen, pkt, pktlen, &comprloop);
465 w += sldns_str_print(s, slen, "\n");
466 w += sldns_str_print(s, slen, ";; ADDITIONAL SECTION:\n");
467 for(i=0; i<arcount; i++) {
468 w += sldns_wire2str_rr_scan(d, dlen, s, slen, pkt, pktlen, &comprloop);
471 /* other fields: WHEN(time), SERVER(IP) not available here. */
472 w += sldns_str_print(s, slen, ";; MSG SIZE rcvd: %d\n", (int)pktlen);
474 w += print_remainder_hex(";; trailing garbage 0x",
476 w += sldns_str_print(s, slen, "\n");
481 /** scan type, class and ttl and printout, for rr */
482 static int sldns_rr_tcttl_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
489 return w + print_remainder_hex("; Error malformed 0x",
491 /* these print values or 0x.. if none left */
492 t = sldns_read_uint16(*d);
493 c = sldns_read_uint16((*d)+2);
496 w += sldns_wire2str_class_print(s, sl, c);
497 w += sldns_str_print(s, sl, "\t");
498 w += sldns_wire2str_type_print(s, sl, t);
500 return w + sldns_str_print(s, sl, "; Error no ttl");
501 return w + print_remainder_hex(
502 "; Error malformed ttl 0x", d, dl, s, sl);
504 t = sldns_read_uint16(*d);
505 c = sldns_read_uint16((*d)+2);
506 ttl = sldns_read_uint32((*d)+4);
509 w += sldns_str_print(s, sl, "%lu\t", (unsigned long)ttl);
510 w += sldns_wire2str_class_print(s, sl, c);
511 w += sldns_str_print(s, sl, "\t");
512 w += sldns_wire2str_type_print(s, sl, t);
516 int sldns_wire2str_rr_scan(uint8_t** d, size_t* dlen, char** s, size_t* slen,
517 uint8_t* pkt, size_t pktlen, int* comprloop)
521 size_t rrlen = *dlen, dname_off, rdlen, ordlen;
524 if(*dlen >= 3 && (*d)[0]==0 &&
525 sldns_read_uint16((*d)+1)==LDNS_RR_TYPE_OPT) {
526 /* perform EDNS OPT processing */
527 return sldns_wire2str_edns_scan(d, dlen, s, slen, pkt, pktlen);
530 /* try to scan the rdata with pretty-printing, but if that fails, then
531 * scan the rdata as an unknown RR type */
532 w += sldns_wire2str_dname_scan(d, dlen, s, slen, pkt, pktlen, comprloop);
533 w += sldns_str_print(s, slen, "\t");
534 dname_off = rrlen-(*dlen);
536 /* like a question-RR */
537 uint16_t t = sldns_read_uint16(*d);
538 uint16_t c = sldns_read_uint16((*d)+2);
541 w += sldns_wire2str_class_print(s, slen, c);
542 w += sldns_str_print(s, slen, "\t");
543 w += sldns_wire2str_type_print(s, slen, t);
544 w += sldns_str_print(s, slen, " ; Error no ttl,rdata\n");
549 return w + sldns_str_print(s, slen, ";Error missing RR\n");
550 w += print_remainder_hex(";Error partial RR 0x", d, dlen, s, slen);
551 return w + sldns_str_print(s, slen, "\n");
553 rrtype = sldns_read_uint16(*d);
554 w += sldns_rr_tcttl_scan(d, dlen, s, slen);
555 w += sldns_str_print(s, slen, "\t");
560 return w + sldns_str_print(s, slen, ";Error missing rdatalen\n");
561 w += print_remainder_hex(";Error missing rdatalen 0x",
563 return w + sldns_str_print(s, slen, "\n");
565 rdlen = sldns_read_uint16(*d);
570 w += sldns_str_print(s, slen, "\\# %u ", (unsigned)rdlen);
572 return w + sldns_str_print(s, slen, ";Error missing rdata\n");
573 w += print_remainder_hex(";Error partial rdata 0x", d, dlen, s, slen);
574 return w + sldns_str_print(s, slen, "\n");
576 w += sldns_wire2str_rdata_scan(d, &rdlen, s, slen, rrtype, pkt, pktlen,
578 (*dlen) -= (ordlen-rdlen);
580 /* default comment */
581 w += sldns_wire2str_rr_comment_print(s, slen, rr, rrlen, dname_off,
583 w += sldns_str_print(s, slen, "\n");
587 int sldns_wire2str_rrquestion_scan(uint8_t** d, size_t* dlen, char** s,
588 size_t* slen, uint8_t* pkt, size_t pktlen, int* comprloop)
592 w += sldns_wire2str_dname_scan(d, dlen, s, slen, pkt, pktlen, comprloop);
593 w += sldns_str_print(s, slen, "\t");
596 return w + sldns_str_print(s, slen, "Error malformed\n");
597 w += print_remainder_hex("Error malformed 0x", d, dlen, s, slen);
598 return w + sldns_str_print(s, slen, "\n");
600 t = sldns_read_uint16(*d);
601 c = sldns_read_uint16((*d)+2);
604 w += sldns_wire2str_class_print(s, slen, c);
605 w += sldns_str_print(s, slen, "\t");
606 w += sldns_wire2str_type_print(s, slen, t);
607 w += sldns_str_print(s, slen, "\n");
611 int sldns_wire2str_rr_unknown_scan(uint8_t** d, size_t* dlen, char** s,
612 size_t* slen, uint8_t* pkt, size_t pktlen, int* comprloop)
614 size_t rdlen, ordlen;
616 w += sldns_wire2str_dname_scan(d, dlen, s, slen, pkt, pktlen, comprloop);
617 w += sldns_str_print(s, slen, "\t");
618 w += sldns_rr_tcttl_scan(d, dlen, s, slen);
619 w += sldns_str_print(s, slen, "\t");
622 return w + sldns_str_print(s, slen, ";Error missing rdatalen\n");
623 w += print_remainder_hex(";Error missing rdatalen 0x",
625 return w + sldns_str_print(s, slen, "\n");
627 rdlen = sldns_read_uint16(*d);
632 w += sldns_str_print(s, slen, "\\# %u ", (unsigned)rdlen);
634 return w + sldns_str_print(s, slen, ";Error missing rdata\n");
635 w += print_remainder_hex(";Error partial rdata 0x", d, dlen, s, slen);
636 return w + sldns_str_print(s, slen, "\n");
638 w += sldns_wire2str_rdata_unknown_scan(d, &rdlen, s, slen);
639 (*dlen) -= (ordlen-rdlen);
640 w += sldns_str_print(s, slen, "\n");
644 /** print rr comment for type DNSKEY */
645 static int rr_comment_dnskey(char** s, size_t* slen, uint8_t* rr,
646 size_t rrlen, size_t dname_off)
651 if(rrlen < dname_off + 10) return 0;
652 rdlen = sldns_read_uint16(rr+dname_off+8);
653 if(rrlen < dname_off + 10 + rdlen) return 0;
654 if(rdlen < 2) return 0;
655 rdata = rr + dname_off + 10;
656 flags = (int)sldns_read_uint16(rdata);
657 w += sldns_str_print(s, slen, " ;{");
660 w += sldns_str_print(s, slen, "id = %u",
661 sldns_calc_keytag_raw(rdata, rdlen));
664 if((flags&LDNS_KEY_ZONE_KEY)) {
665 if((flags&LDNS_KEY_SEP_KEY))
666 w += sldns_str_print(s, slen, " (ksk)");
667 else w += sldns_str_print(s, slen, " (zsk)");
672 w += sldns_str_print(s, slen, ", ");
673 w += sldns_str_print(s, slen, "size = %db",
674 (int)sldns_rr_dnskey_key_size_raw(
675 (unsigned char*)rdata+4, rdlen-4, (int)(rdata[3])));
678 w += sldns_str_print(s, slen, "}");
682 /** print rr comment for type RRSIG */
683 static int rr_comment_rrsig(char** s, size_t* slen, uint8_t* rr,
684 size_t rrlen, size_t dname_off)
688 if(rrlen < dname_off + 10) return 0;
689 rdlen = sldns_read_uint16(rr+dname_off+8);
690 if(rrlen < dname_off + 10 + rdlen) return 0;
691 rdata = rr + dname_off + 10;
692 if(rdlen < 18) return 0;
693 return sldns_str_print(s, slen, " ;{id = %d}",
694 (int)sldns_read_uint16(rdata+16));
697 /** print rr comment for type NSEC3 */
698 static int rr_comment_nsec3(char** s, size_t* slen, uint8_t* rr,
699 size_t rrlen, size_t dname_off)
704 if(rrlen < dname_off + 10) return 0;
705 rdlen = sldns_read_uint16(rr+dname_off+8);
706 if(rrlen < dname_off + 10 + rdlen) return 0;
707 rdata = rr + dname_off + 10;
708 if(rdlen < 2) return 0;
709 if((rdata[1] & LDNS_NSEC3_VARS_OPTOUT_MASK))
710 w += sldns_str_print(s, slen, " ;{flags: optout}");
714 int sldns_wire2str_rr_comment_print(char** s, size_t* slen, uint8_t* rr,
715 size_t rrlen, size_t dname_off, uint16_t rrtype)
717 if(rrtype == LDNS_RR_TYPE_DNSKEY) {
718 return rr_comment_dnskey(s, slen, rr, rrlen, dname_off);
719 } else if(rrtype == LDNS_RR_TYPE_RRSIG) {
720 return rr_comment_rrsig(s, slen, rr, rrlen, dname_off);
721 } else if(rrtype == LDNS_RR_TYPE_NSEC3) {
722 return rr_comment_nsec3(s, slen, rr, rrlen, dname_off);
727 int sldns_wire2str_header_scan(uint8_t** d, size_t* dlen, char** s,
732 w += sldns_str_print(s, slen, ";; ->>HEADER<<- ");
734 return w+sldns_str_print(s, slen, "Error empty packet");
736 return w+print_remainder_hex("Error header too short 0x", d, dlen, s, slen);
737 opcode = (int)LDNS_OPCODE_WIRE(*d);
738 rcode = (int)LDNS_RCODE_WIRE(*d);
739 w += sldns_str_print(s, slen, "opcode: ");
740 w += sldns_wire2str_opcode_print(s, slen, opcode);
741 w += sldns_str_print(s, slen, ", ");
742 w += sldns_str_print(s, slen, "rcode: ");
743 w += sldns_wire2str_rcode_print(s, slen, rcode);
744 w += sldns_str_print(s, slen, ", ");
745 w += sldns_str_print(s, slen, "id: %d\n", (int)LDNS_ID_WIRE(*d));
746 w += sldns_str_print(s, slen, ";; flags:");
747 if(LDNS_QR_WIRE(*d)) w += sldns_str_print(s, slen, " qr");
748 if(LDNS_AA_WIRE(*d)) w += sldns_str_print(s, slen, " aa");
749 if(LDNS_TC_WIRE(*d)) w += sldns_str_print(s, slen, " tc");
750 if(LDNS_RD_WIRE(*d)) w += sldns_str_print(s, slen, " rd");
751 if(LDNS_CD_WIRE(*d)) w += sldns_str_print(s, slen, " cd");
752 if(LDNS_RA_WIRE(*d)) w += sldns_str_print(s, slen, " ra");
753 if(LDNS_AD_WIRE(*d)) w += sldns_str_print(s, slen, " ad");
754 if(LDNS_Z_WIRE(*d)) w += sldns_str_print(s, slen, " z");
755 w += sldns_str_print(s, slen, " ; ");
756 if(*dlen < LDNS_HEADER_SIZE)
757 return w+print_remainder_hex("Error header too short 0x", d, dlen, s, slen);
758 w += sldns_str_print(s, slen, "QUERY: %d, ", (int)LDNS_QDCOUNT(*d));
759 w += sldns_str_print(s, slen, "ANSWER: %d, ", (int)LDNS_ANCOUNT(*d));
760 w += sldns_str_print(s, slen, "AUTHORITY: %d, ", (int)LDNS_NSCOUNT(*d));
761 w += sldns_str_print(s, slen, "ADDITIONAL: %d ", (int)LDNS_ARCOUNT(*d));
762 *d += LDNS_HEADER_SIZE;
763 *dlen -= LDNS_HEADER_SIZE;
767 int sldns_wire2str_rdata_scan(uint8_t** d, size_t* dlen, char** s,
768 size_t* slen, uint16_t rrtype, uint8_t* pkt, size_t pktlen,
771 /* try to prettyprint, but if that fails, use unknown format */
774 size_t origdlen = *dlen, origslen = *slen;
776 sldns_rdf_type rdftype;
779 const sldns_rr_descriptor *desc = sldns_rr_descript(rrtype);
780 if(!desc) /* unknown format */
781 return sldns_wire2str_rdata_unknown_scan(d, dlen, s, slen);
782 /* dlen equals the rdatalen for the rdata */
784 r_max = sldns_rr_descriptor_maximum(desc);
785 for(r_cnt=0; r_cnt < r_max; r_cnt++) {
787 if(r_cnt < sldns_rr_descriptor_minimum(desc))
789 break; /* nothing more to print */
791 rdftype = sldns_rr_descriptor_field_type(desc, r_cnt);
793 w += sldns_str_print(s, slen, " ");
794 n = sldns_wire2str_rdf_scan(d, dlen, s, slen, rdftype,
795 pkt, pktlen, comprloop);
798 /* failed, use unknown format */
799 *d = origd; *s = origs;
800 *dlen = origdlen; *slen = origslen;
801 return sldns_wire2str_rdata_unknown_scan(d, dlen,
812 int sldns_wire2str_rdata_unknown_scan(uint8_t** d, size_t* dlen, char** s,
818 w += sldns_str_print(s, slen, "\\# %u", (unsigned)*dlen);
820 /* print rdlen in hex */
822 w += sldns_str_print(s, slen, " ");
823 w += print_hex_buf(s, slen, *d, *dlen);
829 /** print and escape one character for a domain dname */
830 static int dname_char_print(char** s, size_t* slen, uint8_t c)
832 if(c == '.' || c == ';' || c == '(' || c == ')' || c == '\\')
833 return sldns_str_print(s, slen, "\\%c", c);
834 else if(!(isascii((unsigned char)c) && isgraph((unsigned char)c)))
835 return sldns_str_print(s, slen, "\\%03u", (unsigned)c);
845 int sldns_wire2str_dname_scan(uint8_t** d, size_t* dlen, char** s, size_t* slen,
846 uint8_t* pkt, size_t pktlen, int* comprloop)
849 /* spool labels onto the string, use compression if its there */
851 unsigned i, counter=0;
852 unsigned maxcompr = MAX_COMPRESS_PTRS; /* loop detection, max compr ptrs */
854 size_t dname_len = 0;
857 maxcompr = 30; /* for like ipv6 reverse name, per label */
859 maxcompr = 4; /* just don't want to spend time, any more */
861 if(*dlen == 0) return sldns_str_print(s, slen, "ErrorMissingDname");
865 return sldns_str_print(s, slen, ".");
867 while((!pkt || pos < pkt+pktlen) && *pos) {
868 /* read label length */
869 uint8_t labellen = *pos++;
870 if(in_buf) { (*d)++; (*dlen)--; }
872 /* find out what sort of label we have */
873 if((labellen&0xc0) == 0xc0) {
876 if(in_buf && *dlen == 0)
877 return w + sldns_str_print(s, slen,
878 "ErrorPartialDname");
879 else if(!in_buf && pos+1 > pkt+pktlen)
880 return w + sldns_str_print(s, slen,
881 "ErrorPartialDname");
882 target = ((labellen&0x3f)<<8) | *pos;
883 if(in_buf) { (*d)++; (*dlen)--; }
884 /* move to target, if possible */
885 if(!pkt || target >= pktlen)
886 return w + sldns_str_print(s, slen,
887 "ErrorComprPtrOutOfBounds");
888 if(counter++ > maxcompr) {
889 if(comprloop && *comprloop < 10)
891 return w + sldns_str_print(s, slen,
892 "ErrorComprPtrLooped");
897 } else if((labellen&0xc0)) {
898 /* notimpl label type */
899 w += sldns_str_print(s, slen,
900 "ErrorLABELTYPE%xIsUnknown",
901 (int)(labellen&0xc0));
905 /* spool label characters, end with '.' */
906 if(in_buf && *dlen < (size_t)labellen)
907 labellen = (uint8_t)*dlen;
908 else if(!in_buf && pos+(size_t)labellen > pkt+pktlen)
909 labellen = (uint8_t)(pkt + pktlen - pos);
910 dname_len += ((size_t)labellen)+1;
911 if(dname_len > LDNS_MAX_DOMAINLEN) {
912 /* dname_len counts the uncompressed length we have
913 * seen so far, and the domain name has become too
914 * long, prevent the loop from printing overly long
916 w += sldns_str_print(s, slen,
917 "ErrorDomainNameTooLong");
920 for(i=0; i<(unsigned)labellen; i++) {
921 w += dname_char_print(s, slen, *pos++);
926 if(*dlen == 0) break;
928 w += sldns_str_print(s, slen, ".");
930 /* skip over final root label */
931 if(in_buf && *dlen > 0) { (*d)++; (*dlen)--; }
932 /* in case we printed no labels, terminate dname */
933 if(w == 0) w += sldns_str_print(s, slen, ".");
937 int sldns_wire2str_opcode_print(char** s, size_t* slen, int opcode)
939 sldns_lookup_table *lt = sldns_lookup_by_id(sldns_opcodes, opcode);
940 if (lt && lt->name) {
941 return sldns_str_print(s, slen, "%s", lt->name);
943 return sldns_str_print(s, slen, "OPCODE%u", (unsigned)opcode);
946 int sldns_wire2str_rcode_print(char** s, size_t* slen, int rcode)
948 sldns_lookup_table *lt = sldns_lookup_by_id(sldns_rcodes, rcode);
949 if (lt && lt->name) {
950 return sldns_str_print(s, slen, "%s", lt->name);
952 return sldns_str_print(s, slen, "RCODE%u", (unsigned)rcode);
955 int sldns_wire2str_class_print(char** s, size_t* slen, uint16_t rrclass)
957 sldns_lookup_table *lt = sldns_lookup_by_id(sldns_rr_classes,
959 if (lt && lt->name) {
960 return sldns_str_print(s, slen, "%s", lt->name);
962 return sldns_str_print(s, slen, "CLASS%u", (unsigned)rrclass);
965 int sldns_wire2str_type_print(char** s, size_t* slen, uint16_t rrtype)
967 const sldns_rr_descriptor *descriptor = sldns_rr_descript(rrtype);
968 if (descriptor && descriptor->_name) {
969 return sldns_str_print(s, slen, "%s", descriptor->_name);
971 return sldns_str_print(s, slen, "TYPE%u", (unsigned)rrtype);
974 int sldns_wire2str_edns_option_code_print(char** s, size_t* slen,
977 sldns_lookup_table *lt = sldns_lookup_by_id(sldns_edns_options,
979 if (lt && lt->name) {
980 return sldns_str_print(s, slen, "%s", lt->name);
982 return sldns_str_print(s, slen, "OPT%u", (unsigned)opcode);
985 int sldns_wire2str_class_scan(uint8_t** d, size_t* dlen, char** s, size_t* slen)
988 if(*dlen == 0) return 0;
989 if(*dlen < 2) return print_remainder_hex("Error malformed 0x", d, dlen, s, slen);
990 c = sldns_read_uint16(*d);
993 return sldns_wire2str_class_print(s, slen, c);
996 int sldns_wire2str_type_scan(uint8_t** d, size_t* dlen, char** s, size_t* slen)
999 if(*dlen == 0) return 0;
1000 if(*dlen < 2) return print_remainder_hex("Error malformed 0x", d, dlen, s, slen);
1001 t = sldns_read_uint16(*d);
1004 return sldns_wire2str_type_print(s, slen, t);
1007 int sldns_wire2str_ttl_scan(uint8_t** d, size_t* dlen, char** s, size_t* slen)
1010 if(*dlen == 0) return 0;
1011 if(*dlen < 4) return print_remainder_hex("Error malformed 0x", d, dlen, s, slen);
1012 ttl = sldns_read_uint32(*d);
1015 return sldns_str_print(s, slen, "%u", (unsigned)ttl);
1019 sldns_print_svcparamkey(char** s, size_t* slen, uint16_t svcparamkey)
1021 if (svcparamkey < SVCPARAMKEY_COUNT) {
1022 return sldns_str_print(s, slen, "%s", svcparamkey_strs[svcparamkey]);
1025 return sldns_str_print(s, slen, "key%d", (int)svcparamkey);
1029 static int sldns_wire2str_svcparam_port2str(char** s,
1030 size_t* slen, uint16_t data_len, uint8_t* data)
1035 return -1; /* wireformat error, a short is 2 bytes */
1036 w = sldns_str_print(s, slen, "=%d", (int)sldns_read_uint16(data));
1041 static int sldns_wire2str_svcparam_ipv4hint2str(char** s,
1042 size_t* slen, uint16_t data_len, uint8_t* data)
1044 char ip_str[INET_ADDRSTRLEN + 1];
1048 assert(data_len > 0);
1050 if ((data_len % LDNS_IP4ADDRLEN) == 0) {
1051 if (inet_ntop(AF_INET, data, ip_str, sizeof(ip_str)) == NULL)
1052 return -1; /* wireformat error, incorrect size or inet family */
1054 w += sldns_str_print(s, slen, "=%s", ip_str);
1055 data += LDNS_IP4ADDRLEN;
1057 while ((data_len -= LDNS_IP4ADDRLEN) > 0) {
1058 if (inet_ntop(AF_INET, data, ip_str, sizeof(ip_str)) == NULL)
1059 return -1; /* wireformat error, incorrect size or inet family */
1061 w += sldns_str_print(s, slen, ",%s", ip_str);
1062 data += LDNS_IP4ADDRLEN;
1070 static int sldns_wire2str_svcparam_ipv6hint2str(char** s,
1071 size_t* slen, uint16_t data_len, uint8_t* data)
1073 char ip_str[INET6_ADDRSTRLEN + 1];
1077 assert(data_len > 0);
1079 if ((data_len % LDNS_IP6ADDRLEN) == 0) {
1080 if (inet_ntop(AF_INET6, data, ip_str, sizeof(ip_str)) == NULL)
1081 return -1; /* wireformat error, incorrect size or inet family */
1083 w += sldns_str_print(s, slen, "=%s", ip_str);
1084 data += LDNS_IP6ADDRLEN;
1086 while ((data_len -= LDNS_IP6ADDRLEN) > 0) {
1087 if (inet_ntop(AF_INET6, data, ip_str, sizeof(ip_str)) == NULL)
1088 return -1; /* wireformat error, incorrect size or inet family */
1090 w += sldns_str_print(s, slen, ",%s", ip_str);
1091 data += LDNS_IP6ADDRLEN;
1099 static int sldns_wire2str_svcparam_mandatory2str(char** s,
1100 size_t* slen, uint16_t data_len, uint8_t* data)
1104 assert(data_len > 0);
1106 if (data_len % sizeof(uint16_t))
1107 return -1; /* wireformat error, data_len must be multiple of shorts */
1108 w += sldns_str_print(s, slen, "=");
1109 w += sldns_print_svcparamkey(s, slen, sldns_read_uint16(data));
1112 while ((data_len -= sizeof(uint16_t))) {
1113 w += sldns_str_print(s, slen, ",");
1114 w += sldns_print_svcparamkey(s, slen, sldns_read_uint16(data));
1121 static int sldns_wire2str_svcparam_alpn2str(char** s,
1122 size_t* slen, uint16_t data_len, uint8_t* data)
1124 uint8_t *dp = (void *)data;
1127 assert(data_len > 0); /* Guaranteed by sldns_wire2str_svcparam_scan */
1129 w += sldns_str_print(s, slen, "=\"");
1131 /* alpn is list of length byte (str_len) followed by a string of that size */
1132 uint8_t i, str_len = *dp++;
1134 if (str_len > --data_len)
1137 for (i = 0; i < str_len; i++) {
1138 if (dp[i] == '"' || dp[i] == '\\')
1139 w += sldns_str_print(s, slen, "\\\\\\%c", dp[i]);
1141 else if (dp[i] == ',')
1142 w += sldns_str_print(s, slen, "\\\\%c", dp[i]);
1144 else if (!isprint(dp[i]))
1145 w += sldns_str_print(s, slen, "\\%03u", (unsigned) dp[i]);
1148 w += sldns_str_print(s, slen, "%c", dp[i]);
1151 if ((data_len -= str_len))
1152 w += sldns_str_print(s, slen, "%s", ",");
1154 w += sldns_str_print(s, slen, "\"");
1159 static int sldns_wire2str_svcparam_ech2str(char** s,
1160 size_t* slen, uint16_t data_len, uint8_t* data)
1165 assert(data_len > 0); /* Guaranteed by sldns_wire2str_svcparam_scan */
1167 w += sldns_str_print(s, slen, "=\"");
1169 if ((size = sldns_b64_ntop(data, data_len, *s, *slen)) < 0)
1175 w += sldns_str_print(s, slen, "\"");
1180 int sldns_wire2str_svcparam_scan(uint8_t** d, size_t* dlen, char** s, size_t* slen)
1183 uint16_t svcparamkey, data_len;
1184 int written_chars = 0;
1187 /* verify that we have enough data to read svcparamkey and data_len */
1191 svcparamkey = sldns_read_uint16(*d);
1192 data_len = sldns_read_uint16(*d+2);
1196 /* verify that we have data_len data */
1197 if (data_len > *dlen)
1200 written_chars += sldns_print_svcparamkey(s, slen, svcparamkey);
1203 /* Some SvcParams MUST have values */
1204 switch (svcparamkey) {
1207 case SVCB_KEY_IPV4HINT:
1208 case SVCB_KEY_IPV6HINT:
1209 case SVCB_KEY_MANDATORY:
1210 case SVCB_KEY_DOHPATH:
1213 return written_chars;
1217 switch (svcparamkey) {
1219 r = sldns_wire2str_svcparam_port2str(s, slen, data_len, *d);
1221 case SVCB_KEY_IPV4HINT:
1222 r = sldns_wire2str_svcparam_ipv4hint2str(s, slen, data_len, *d);
1224 case SVCB_KEY_IPV6HINT:
1225 r = sldns_wire2str_svcparam_ipv6hint2str(s, slen, data_len, *d);
1227 case SVCB_KEY_MANDATORY:
1228 r = sldns_wire2str_svcparam_mandatory2str(s, slen, data_len, *d);
1230 case SVCB_KEY_NO_DEFAULT_ALPN:
1231 return -1; /* wireformat error, should not have a value */
1233 r = sldns_wire2str_svcparam_alpn2str(s, slen, data_len, *d);
1236 r = sldns_wire2str_svcparam_ech2str(s, slen, data_len, *d);
1238 case SVCB_KEY_DOHPATH:
1241 r = sldns_str_print(s, slen, "=\"");
1243 for (i = 0; i < data_len; i++) {
1246 if (ch == '"' || ch == '\\')
1247 r += sldns_str_print(s, slen, "\\%c", ch);
1249 else if (!isprint(ch))
1250 r += sldns_str_print(s, slen, "\\%03u", (unsigned) ch);
1253 r += sldns_str_print(s, slen, "%c", ch);
1256 r += sldns_str_print(s, slen, "\"");
1260 return -1; /* wireformat error */
1265 return written_chars;
1268 int sldns_wire2str_rdf_scan(uint8_t** d, size_t* dlen, char** s, size_t* slen,
1269 int rdftype, uint8_t* pkt, size_t pktlen, int* comprloop)
1271 if(*dlen == 0) return 0;
1273 case LDNS_RDF_TYPE_NONE:
1275 case LDNS_RDF_TYPE_DNAME:
1276 return sldns_wire2str_dname_scan(d, dlen, s, slen, pkt, pktlen, comprloop);
1277 case LDNS_RDF_TYPE_INT8:
1278 return sldns_wire2str_int8_scan(d, dlen, s, slen);
1279 case LDNS_RDF_TYPE_INT16:
1280 return sldns_wire2str_int16_scan(d, dlen, s, slen);
1281 case LDNS_RDF_TYPE_INT32:
1282 return sldns_wire2str_int32_scan(d, dlen, s, slen);
1283 case LDNS_RDF_TYPE_PERIOD:
1284 return sldns_wire2str_period_scan(d, dlen, s, slen);
1285 case LDNS_RDF_TYPE_TSIGTIME:
1286 return sldns_wire2str_tsigtime_scan(d, dlen, s, slen);
1287 case LDNS_RDF_TYPE_A:
1288 return sldns_wire2str_a_scan(d, dlen, s, slen);
1289 case LDNS_RDF_TYPE_AAAA:
1290 return sldns_wire2str_aaaa_scan(d, dlen, s, slen);
1291 case LDNS_RDF_TYPE_STR:
1292 return sldns_wire2str_str_scan(d, dlen, s, slen);
1293 case LDNS_RDF_TYPE_APL:
1294 return sldns_wire2str_apl_scan(d, dlen, s, slen);
1295 case LDNS_RDF_TYPE_B32_EXT:
1296 return sldns_wire2str_b32_ext_scan(d, dlen, s, slen);
1297 case LDNS_RDF_TYPE_B64:
1298 return sldns_wire2str_b64_scan(d, dlen, s, slen);
1299 case LDNS_RDF_TYPE_HEX:
1300 return sldns_wire2str_hex_scan(d, dlen, s, slen);
1301 case LDNS_RDF_TYPE_NSEC:
1302 return sldns_wire2str_nsec_scan(d, dlen, s, slen);
1303 case LDNS_RDF_TYPE_NSEC3_SALT:
1304 return sldns_wire2str_nsec3_salt_scan(d, dlen, s, slen);
1305 case LDNS_RDF_TYPE_TYPE:
1306 return sldns_wire2str_type_scan(d, dlen, s, slen);
1307 case LDNS_RDF_TYPE_CLASS:
1308 return sldns_wire2str_class_scan(d, dlen, s, slen);
1309 case LDNS_RDF_TYPE_CERT_ALG:
1310 return sldns_wire2str_cert_alg_scan(d, dlen, s, slen);
1311 case LDNS_RDF_TYPE_ALG:
1312 return sldns_wire2str_alg_scan(d, dlen, s, slen);
1313 case LDNS_RDF_TYPE_UNKNOWN:
1314 return sldns_wire2str_unknown_scan(d, dlen, s, slen);
1315 case LDNS_RDF_TYPE_TIME:
1316 return sldns_wire2str_time_scan(d, dlen, s, slen);
1317 case LDNS_RDF_TYPE_LOC:
1318 return sldns_wire2str_loc_scan(d, dlen, s, slen);
1319 case LDNS_RDF_TYPE_WKS:
1320 case LDNS_RDF_TYPE_SERVICE:
1321 return sldns_wire2str_wks_scan(d, dlen, s, slen);
1322 case LDNS_RDF_TYPE_NSAP:
1323 return sldns_wire2str_nsap_scan(d, dlen, s, slen);
1324 case LDNS_RDF_TYPE_ATMA:
1325 return sldns_wire2str_atma_scan(d, dlen, s, slen);
1326 case LDNS_RDF_TYPE_IPSECKEY:
1327 return sldns_wire2str_ipseckey_scan(d, dlen, s, slen, pkt,
1329 case LDNS_RDF_TYPE_HIP:
1330 return sldns_wire2str_hip_scan(d, dlen, s, slen);
1331 case LDNS_RDF_TYPE_INT16_DATA:
1332 return sldns_wire2str_int16_data_scan(d, dlen, s, slen);
1333 case LDNS_RDF_TYPE_NSEC3_NEXT_OWNER:
1334 return sldns_wire2str_b32_ext_scan(d, dlen, s, slen);
1335 case LDNS_RDF_TYPE_ILNP64:
1336 return sldns_wire2str_ilnp64_scan(d, dlen, s, slen);
1337 case LDNS_RDF_TYPE_EUI48:
1338 return sldns_wire2str_eui48_scan(d, dlen, s, slen);
1339 case LDNS_RDF_TYPE_EUI64:
1340 return sldns_wire2str_eui64_scan(d, dlen, s, slen);
1341 case LDNS_RDF_TYPE_TAG:
1342 return sldns_wire2str_tag_scan(d, dlen, s, slen);
1343 case LDNS_RDF_TYPE_LONG_STR:
1344 return sldns_wire2str_long_str_scan(d, dlen, s, slen);
1345 case LDNS_RDF_TYPE_SVCPARAM:
1346 return sldns_wire2str_svcparam_scan(d, dlen, s, slen);
1347 case LDNS_RDF_TYPE_TSIGERROR:
1348 return sldns_wire2str_tsigerror_scan(d, dlen, s, slen);
1350 /* unknown rdf type */
1354 int sldns_wire2str_int8_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
1357 if(*dl < 1) return -1;
1358 w = sldns_str_print(s, sl, "%u", (unsigned)**d);
1364 int sldns_wire2str_int16_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
1367 if(*dl < 2) return -1;
1368 w = sldns_str_print(s, sl, "%lu", (unsigned long)sldns_read_uint16(*d));
1374 int sldns_wire2str_int32_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
1377 if(*dl < 4) return -1;
1378 w = sldns_str_print(s, sl, "%lu", (unsigned long)sldns_read_uint32(*d));
1384 int sldns_wire2str_period_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
1387 if(*dl < 4) return -1;
1388 w = sldns_str_print(s, sl, "%u", (unsigned)sldns_read_uint32(*d));
1394 int sldns_wire2str_tsigtime_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
1396 /* tsigtime is 48 bits network order unsigned integer */
1398 uint64_t tsigtime = 0;
1399 uint64_t d0, d1, d2, d3, d4, d5;
1400 if(*dl < 6) return -1;
1401 d0 = (*d)[0]; /* cast to uint64 for shift operations */
1407 tsigtime = (d0<<40) | (d1<<32) | (d2<<24) | (d3<<16) | (d4<<8) | d5;
1409 w = sldns_str_print(s, sl, "%llu", (long long)tsigtime);
1411 w = sldns_str_print(s, sl, "%I64u", (long long)tsigtime);
1418 int sldns_wire2str_a_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
1422 if(*dl < 4) return -1;
1423 if(!inet_ntop(AF_INET, *d, buf, (socklen_t)sizeof(buf)))
1425 w = sldns_str_print(s, sl, "%s", buf);
1431 int sldns_wire2str_aaaa_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
1436 if(*dl < 16) return -1;
1437 if(!inet_ntop(AF_INET6, *d, buf, (socklen_t)sizeof(buf)))
1439 w = sldns_str_print(s, sl, "%s", buf);
1448 /** printout escaped TYPE_STR character */
1449 static int str_char_print(char** s, size_t* sl, uint8_t c)
1451 if(isprint((unsigned char)c) || c == '\t') {
1452 if(c == '\"' || c == '\\')
1453 return sldns_str_print(s, sl, "\\%c", c);
1461 return sldns_str_print(s, sl, "\\%03u", (unsigned)c);
1464 int sldns_wire2str_str_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
1468 if(*dl < 1) return -1;
1470 if(*dl < 1+len) return -1;
1473 w += sldns_str_print(s, sl, "\"");
1474 for(i=0; i<len; i++)
1475 w += str_char_print(s, sl, (*d)[i]);
1476 w += sldns_str_print(s, sl, "\"");
1482 int sldns_wire2str_apl_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
1486 uint8_t negation, prefix, adflength;
1487 if(*dl < 4) return -1;
1488 family = sldns_read_uint16(*d);
1490 negation = ((*d)[3] & LDNS_APL_NEGATION);
1491 adflength = ((*d)[3] & LDNS_APL_MASK);
1492 if(*dl < 4+(size_t)adflength) return -1;
1493 if(family != LDNS_APL_IP4 && family != LDNS_APL_IP6)
1494 return -1; /* unknown address family */
1496 w += sldns_str_print(s, sl, "!");
1497 w += sldns_str_print(s, sl, "%u:", (unsigned)family);
1498 if(family == LDNS_APL_IP4) {
1499 /* check if prefix <32 ? */
1500 /* address is variable length 0 - 4 */
1501 for(i=0; i<4; i++) {
1503 w += sldns_str_print(s, sl, ".");
1504 if(i < (int)adflength)
1505 w += sldns_str_print(s, sl, "%d", (*d)[4+i]);
1506 else w += sldns_str_print(s, sl, "0");
1508 } else if(family == LDNS_APL_IP6) {
1509 /* check if prefix <128 ? */
1510 /* address is variable length 0 - 16 */
1511 for(i=0; i<16; i++) {
1513 w += sldns_str_print(s, sl, ":");
1514 if(i < (int)adflength)
1515 w += sldns_str_print(s, sl, "%02x", (*d)[4+i]);
1516 else w += sldns_str_print(s, sl, "00");
1519 w += sldns_str_print(s, sl, "/%u", (unsigned)prefix);
1520 (*d) += 4+adflength;
1521 (*dl) -= 4+adflength;
1525 int sldns_wire2str_b32_ext_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
1529 if(*dl < 1) return -1;
1531 if(*dl < 1+datalen) return -1;
1532 sz = sldns_b32_ntop_calculate_size(datalen);
1535 (*dl) -= (datalen+1);
1536 return (int)sz; /* out of space really, but would need buffer
1537 in order to truncate the output */
1539 sldns_b32_ntop_extended_hex((*d)+1, datalen, *s, *sl);
1541 (*dl) -= (datalen+1);
1547 /** scan number of bytes from wire into b64 presentation format */
1548 static int sldns_wire2str_b64_scan_num(uint8_t** d, size_t* dl, char** s,
1549 size_t* sl, size_t num)
1551 /* b64_ntop_calculate size includes null at the end */
1552 size_t sz = sldns_b64_ntop_calculate_size(num)-1;
1556 return (int)sz; /* out of space really, but would need buffer
1557 in order to truncate the output */
1559 sldns_b64_ntop(*d, num, *s, *sl);
1567 int sldns_wire2str_b64_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
1570 return sldns_str_print(s, sl, "0");
1572 return sldns_wire2str_b64_scan_num(d, dl, s, sl, *dl);
1575 int sldns_wire2str_hex_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
1578 return sldns_str_print(s, sl, "0");
1580 return print_remainder_hex("", d, dl, s, sl);
1583 int sldns_wire2str_nsec_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
1587 unsigned i, bit, window, block_len;
1591 /* check for errors */
1593 if(pl < 2) return -1;
1594 block_len = (unsigned)p[1];
1595 if(pl < 2+block_len) return -1;
1604 if(pl < 2) return -1; /* cannot happen */
1605 window = (unsigned)p[0];
1606 block_len = (unsigned)p[1];
1607 if(pl < 2+block_len) return -1; /* cannot happen */
1609 for(i=0; i<block_len; i++) {
1610 if(p[i] == 0) continue;
1611 /* base type number for this octet */
1612 t = ((window)<<8) | (i << 3);
1613 for(bit=0; bit<8; bit++) {
1614 if((p[i]&(0x80>>bit))) {
1615 if(w) w += sldns_str_print(s, sl, " ");
1616 w += sldns_wire2str_type_print(s, sl,
1629 int sldns_wire2str_nsec3_salt_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
1633 if(*dl < 1) return -1;
1634 salt_len = (size_t)(*d)[0];
1635 if(*dl < 1+salt_len) return -1;
1639 return sldns_str_print(s, sl, "-");
1641 w = print_hex_buf(s, sl, *d, salt_len);
1647 int sldns_wire2str_cert_alg_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
1649 sldns_lookup_table *lt;
1651 if(*dl < 2) return -1;
1652 data = (int)sldns_read_uint16(*d);
1653 lt = sldns_lookup_by_id(sldns_cert_algorithms, data);
1655 w = sldns_str_print(s, sl, "%s", lt->name);
1656 else w = sldns_str_print(s, sl, "%d", data);
1662 int sldns_wire2str_alg_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
1664 /* don't use algorithm mnemonics in the presentation format
1665 * this kind of got sneaked into the rfc's */
1666 return sldns_wire2str_int8_scan(d, dl, s, sl);
1669 int sldns_wire2str_unknown_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
1671 return sldns_wire2str_rdata_unknown_scan(d, dl, s, sl);
1674 int sldns_wire2str_time_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
1676 /* create a YYYYMMDDHHMMSS string if possible */
1680 memset(&tm, 0, sizeof(tm));
1681 if(*dl < 4) return -1;
1682 t = sldns_read_uint32(*d);
1684 if(sldns_serial_arithmetics_gmtime_r(t, time(NULL), &tm) &&
1685 strftime(date_buf, 15, "%Y%m%d%H%M%S", &tm)) {
1688 return sldns_str_print(s, sl, "%s", date_buf);
1694 loc_cm_print(char** str, size_t* sl, uint8_t mantissa, uint8_t exponent)
1698 /* is it 0.<two digits> ? */
1702 return sldns_str_print(str, sl, "0.%02ld", (long)mantissa);
1704 /* always <digit><string of zeros> */
1705 w += sldns_str_print(str, sl, "%d", (int)mantissa);
1706 for(i=0; i<exponent-2; i++)
1707 w += sldns_str_print(str, sl, "0");
1711 int sldns_wire2str_loc_scan(uint8_t** d, size_t* dl, char** str, size_t* sl)
1713 /* we could do checking (ie degrees < 90 etc)? */
1716 uint8_t horizontal_precision;
1717 uint8_t vertical_precision;
1726 uint32_t equator = (uint32_t)1 << 31; /* 2**31 */
1729 if(*dl < 16) return -1;
1732 return sldns_wire2str_hex_scan(d, dl, str, sl);
1734 horizontal_precision = (*d)[2];
1735 vertical_precision = (*d)[3];
1737 latitude = sldns_read_uint32((*d)+4);
1738 longitude = sldns_read_uint32((*d)+8);
1739 altitude = sldns_read_uint32((*d)+12);
1741 if (latitude > equator) {
1743 latitude = latitude - equator;
1746 latitude = equator - latitude;
1748 h = latitude / (1000 * 60 * 60);
1749 latitude = latitude % (1000 * 60 * 60);
1750 m = latitude / (1000 * 60);
1751 latitude = latitude % (1000 * 60);
1752 s = (double) latitude / 1000.0;
1753 w += sldns_str_print(str, sl, "%02u %02u %06.3f %c ",
1754 h, m, s, northerness);
1756 if (longitude > equator) {
1758 longitude = longitude - equator;
1761 longitude = equator - longitude;
1763 h = longitude / (1000 * 60 * 60);
1764 longitude = longitude % (1000 * 60 * 60);
1765 m = longitude / (1000 * 60);
1766 longitude = longitude % (1000 * 60);
1767 s = (double) longitude / (1000.0);
1768 w += sldns_str_print(str, sl, "%02u %02u %06.3f %c ",
1769 h, m, s, easterness);
1771 s = ((double) altitude) / 100;
1774 if(altitude%100 != 0)
1775 w += sldns_str_print(str, sl, "%.2f", s);
1777 w += sldns_str_print(str, sl, "%.0f", s);
1779 w += sldns_str_print(str, sl, "m ");
1781 w += loc_cm_print(str, sl, (size & 0xf0) >> 4, size & 0x0f);
1782 w += sldns_str_print(str, sl, "m ");
1784 w += loc_cm_print(str, sl, (horizontal_precision & 0xf0) >> 4,
1785 horizontal_precision & 0x0f);
1786 w += sldns_str_print(str, sl, "m ");
1788 w += loc_cm_print(str, sl, (vertical_precision & 0xf0) >> 4,
1789 vertical_precision & 0x0f);
1790 w += sldns_str_print(str, sl, "m");
1797 int sldns_wire2str_wks_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
1799 /* protocol, followed by bitmap of services */
1800 const char* proto_name = NULL;
1801 struct protoent *protocol;
1802 struct servent *service;
1803 uint8_t protocol_nr;
1804 int bit, port, w = 0;
1806 /* we cannot print with strings because they
1807 * are not portable, the presentation format may
1808 * not be able to be read in on another computer. */
1809 int print_symbols = 0;
1812 if(*dl < 1) return -1;
1813 protocol_nr = (*d)[0];
1816 protocol = getprotobynumber((int)protocol_nr);
1817 if(protocol && (protocol->p_name != NULL)) {
1818 w += sldns_str_print(s, sl, "%s", protocol->p_name);
1819 proto_name = protocol->p_name;
1820 } else if(protocol_nr == 6) {
1821 w += sldns_str_print(s, sl, "tcp");
1822 } else if(protocol_nr == 17) {
1823 w += sldns_str_print(s, sl, "udp");
1825 w += sldns_str_print(s, sl, "%u", (unsigned)protocol_nr);
1828 for(i=0; i<*dl; i++) {
1831 for(bit=0; bit<8; bit++) {
1832 if(!(((*d)[i])&(0x80>>bit)))
1834 port = (int)i*8 + bit;
1839 service = getservbyport(
1840 (int)htons((uint16_t)port), proto_name);
1841 if(service && service->s_name)
1842 w += sldns_str_print(s, sl, " %s",
1844 else w += sldns_str_print(s, sl, " %u",
1849 #ifdef HAVE_ENDSERVENT
1852 #ifdef HAVE_ENDPROTOENT
1860 int sldns_wire2str_nsap_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
1862 return print_remainder_hex("0x", d, dl, s, sl);
1865 int sldns_wire2str_atma_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
1867 return print_remainder_hex("", d, dl, s, sl);
1870 /* internal scan routine that can modify arguments on failure */
1871 static int sldns_wire2str_ipseckey_scan_internal(uint8_t** d, size_t* dl,
1872 char** s, size_t* sl, uint8_t* pkt, size_t pktlen, int* comprloop)
1874 /* http://www.ietf.org/internet-drafts/draft-ietf-ipseckey-rr-12.txt*/
1875 uint8_t precedence, gateway_type, algorithm;
1878 if(*dl < 3) return -1;
1879 precedence = (*d)[0];
1880 gateway_type = (*d)[1];
1881 algorithm = (*d)[2];
1882 if(gateway_type > 3)
1883 return -1; /* unknown */
1886 w += sldns_str_print(s, sl, "%d %d %d ",
1887 (int)precedence, (int)gateway_type, (int)algorithm);
1889 switch(gateway_type) {
1890 case 0: /* no gateway */
1891 w += sldns_str_print(s, sl, ".");
1894 w += sldns_wire2str_a_scan(d, dl, s, sl);
1897 w += sldns_wire2str_aaaa_scan(d, dl, s, sl);
1900 w += sldns_wire2str_dname_scan(d, dl, s, sl, pkt, pktlen, comprloop);
1902 default: /* unknown */
1908 w += sldns_str_print(s, sl, " ");
1909 w += sldns_wire2str_b64_scan_num(d, dl, s, sl, *dl);
1913 int sldns_wire2str_ipseckey_scan(uint8_t** d, size_t* dl, char** s, size_t* sl,
1914 uint8_t* pkt, size_t pktlen, int* comprloop)
1918 size_t odl = *dl, osl = *sl;
1919 int w=sldns_wire2str_ipseckey_scan_internal(d, dl, s, sl, pkt, pktlen, comprloop);
1930 int sldns_wire2str_hip_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
1933 uint8_t algo, hitlen;
1941 pklen = sldns_read_uint16((*d)+2);
1942 if(*dl < (size_t)4 + (size_t)hitlen + (size_t)pklen)
1945 /* write: algo hit pubkey */
1946 w = sldns_str_print(s, sl, "%u ", (unsigned)algo);
1947 w += print_hex_buf(s, sl, (*d)+4, hitlen);
1948 w += sldns_str_print(s, sl, " ");
1951 w += sldns_wire2str_b64_scan_num(d, dl, s, sl, pklen);
1955 int sldns_wire2str_int16_data_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
1961 n = sldns_read_uint16(*d);
1962 if(*dl < 2+(size_t)n)
1967 return sldns_str_print(s, sl, "0");
1969 w = sldns_str_print(s, sl, "%u ", (unsigned)n);
1970 w += sldns_wire2str_b64_scan_num(d, dl, s, sl, n);
1974 int sldns_wire2str_nsec3_next_owner_scan(uint8_t** d, size_t* dl, char** s,
1977 return sldns_wire2str_b32_ext_scan(d, dl, s, sl);
1980 int sldns_wire2str_ilnp64_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
1985 w = sldns_str_print(s, sl, "%.4x:%.4x:%.4x:%.4x",
1986 sldns_read_uint16(*d), sldns_read_uint16((*d)+2),
1987 sldns_read_uint16((*d)+4), sldns_read_uint16((*d)+6));
1993 int sldns_wire2str_eui48_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
1998 w = sldns_str_print(s, sl, "%.2x-%.2x-%.2x-%.2x-%.2x-%.2x",
1999 (*d)[0], (*d)[1], (*d)[2], (*d)[3], (*d)[4], (*d)[5]);
2005 int sldns_wire2str_eui64_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
2010 w = sldns_str_print(s, sl, "%.2x-%.2x-%.2x-%.2x-%.2x-%.2x-%.2x-%.2x",
2011 (*d)[0], (*d)[1], (*d)[2], (*d)[3], (*d)[4], (*d)[5],
2018 int sldns_wire2str_tag_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
2024 n = (size_t)((*d)[0]);
2028 if(!isalnum((unsigned char)(*d)[i+1]))
2031 w += sldns_str_print(s, sl, "%c", (char)(*d)[i+1]);
2037 int sldns_wire2str_long_str_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
2041 w += sldns_str_print(s, sl, "\"");
2042 for(i=0; i<*dl; i++)
2043 w += str_char_print(s, sl, (*d)[i]);
2044 w += sldns_str_print(s, sl, "\"");
2050 int sldns_wire2str_tsigerror_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
2052 sldns_lookup_table *lt;
2054 if(*dl < 2) return -1;
2055 data = (int)sldns_read_uint16(*d);
2056 lt = sldns_lookup_by_id(sldns_tsig_errors, data);
2058 w = sldns_str_print(s, sl, "%s", lt->name);
2059 else w = sldns_str_print(s, sl, "%d", data);
2065 int sldns_wire2str_edns_llq_print(char** s, size_t* sl, uint8_t* data,
2069 const char* llq_errors[] = {"NO-ERROR", "SERV-FULL", "STATIC",
2070 "FORMAT-ERR", "NO-SUCH-LLQ", "BAD-VERS", "UNKNOWN_ERR"};
2071 const unsigned int llq_errors_num = 7;
2072 const char* llq_opcodes[] = {"LLQ-SETUP", "LLQ-REFRESH", "LLQ-EVENT"};
2073 const unsigned int llq_opcodes_num = 3;
2074 uint16_t version, llq_opcode, error_code;
2076 uint32_t lease_life; /* Requested or granted life of LLQ, in seconds */
2079 /* read the record */
2081 w += sldns_str_print(s, sl, "malformed LLQ ");
2082 w += print_hex_buf(s, sl, data, len);
2085 version = sldns_read_uint16(data);
2086 llq_opcode = sldns_read_uint16(data+2);
2087 error_code = sldns_read_uint16(data+4);
2088 memmove(&llq_id, data+6, sizeof(llq_id));
2089 lease_life = sldns_read_uint32(data+14);
2092 w += sldns_str_print(s, sl, "v%d ", (int)version);
2093 if(llq_opcode < llq_opcodes_num)
2094 w += sldns_str_print(s, sl, "%s", llq_opcodes[llq_opcode]);
2095 else w += sldns_str_print(s, sl, "opcode %d", (int)llq_opcode);
2096 if(error_code < llq_errors_num)
2097 w += sldns_str_print(s, sl, " %s", llq_errors[error_code]);
2098 else w += sldns_str_print(s, sl, " error %d", (int)error_code);
2100 w += sldns_str_print(s, sl, " id %llx lease-life %lu",
2101 (unsigned long long)llq_id, (unsigned long)lease_life);
2103 w += sldns_str_print(s, sl, " id %I64x lease-life %lu",
2104 (unsigned long long)llq_id, (unsigned long)lease_life);
2109 int sldns_wire2str_edns_ul_print(char** s, size_t* sl, uint8_t* data,
2115 w += sldns_str_print(s, sl, "malformed UL ");
2116 w += print_hex_buf(s, sl, data, len);
2119 lease = sldns_read_uint32(data);
2120 w += sldns_str_print(s, sl, "lease %lu", (unsigned long)lease);
2124 int sldns_wire2str_edns_nsid_print(char** s, size_t* sl, uint8_t* data,
2128 size_t i, printed=0;
2129 w += print_hex_buf(s, sl, data, len);
2130 for(i=0; i<len; i++) {
2131 if(isprint((unsigned char)data[i]) || data[i] == '\t') {
2133 w += sldns_str_print(s, sl, " (");
2136 w += sldns_str_print(s, sl, "%c", (char)data[i]);
2140 w += sldns_str_print(s, sl, ")");
2144 int sldns_wire2str_edns_dau_print(char** s, size_t* sl, uint8_t* data,
2147 sldns_lookup_table *lt;
2150 for(i=0; i<len; i++) {
2151 lt = sldns_lookup_by_id(sldns_algorithms, (int)data[i]);
2153 w += sldns_str_print(s, sl, " %s", lt->name);
2154 else w += sldns_str_print(s, sl, " %d", (int)data[i]);
2159 int sldns_wire2str_edns_dhu_print(char** s, size_t* sl, uint8_t* data,
2162 sldns_lookup_table *lt;
2165 for(i=0; i<len; i++) {
2166 lt = sldns_lookup_by_id(sldns_hashes, (int)data[i]);
2168 w += sldns_str_print(s, sl, " %s", lt->name);
2169 else w += sldns_str_print(s, sl, " %d", (int)data[i]);
2174 int sldns_wire2str_edns_n3u_print(char** s, size_t* sl, uint8_t* data,
2179 for(i=0; i<len; i++) {
2181 w += sldns_str_print(s, sl, " SHA1");
2182 else w += sldns_str_print(s, sl, " %d", (int)data[i]);
2187 int sldns_wire2str_edns_subnet_print(char** s, size_t* sl, uint8_t* data,
2192 uint8_t source, scope;
2194 w += sldns_str_print(s, sl, "malformed subnet ");
2195 w += print_hex_buf(s, sl, data, len);
2198 family = sldns_read_uint16(data);
2205 memset(ip4, 0, sizeof(ip4));
2207 w += sldns_str_print(s, sl, "trailingdata:");
2208 w += print_hex_buf(s, sl, data+4+4, len-4-4);
2209 w += sldns_str_print(s, sl, " ");
2212 memmove(ip4, data+4, len-4);
2213 if(!inet_ntop(AF_INET, ip4, buf, (socklen_t)sizeof(buf))) {
2214 w += sldns_str_print(s, sl, "ip4ntoperror ");
2215 w += print_hex_buf(s, sl, data+4+4, len-4-4);
2217 w += sldns_str_print(s, sl, "%s", buf);
2219 } else if(family == 2) {
2223 memset(ip6, 0, sizeof(ip6));
2225 w += sldns_str_print(s, sl, "trailingdata:");
2226 w += print_hex_buf(s, sl, data+4+16, len-4-16);
2227 w += sldns_str_print(s, sl, " ");
2230 memmove(ip6, data+4, len-4);
2232 if(!inet_ntop(AF_INET6, ip6, buf, (socklen_t)sizeof(buf))) {
2233 w += sldns_str_print(s, sl, "ip6ntoperror ");
2234 w += print_hex_buf(s, sl, data+4+4, len-4-4);
2236 w += sldns_str_print(s, sl, "%s", buf);
2239 w += print_hex_buf(s, sl, data+4+4, len-4-4);
2243 w += sldns_str_print(s, sl, "family %d ",
2245 w += print_hex_buf(s, sl, data, len);
2247 w += sldns_str_print(s, sl, "/%d scope /%d", (int)source, (int)scope);
2251 static int sldns_wire2str_edns_keepalive_print(char** s, size_t* sl,
2252 uint8_t* data, size_t len)
2256 if(!(len == 0 || len == 2)) {
2257 w += sldns_str_print(s, sl, "malformed keepalive ");
2258 w += print_hex_buf(s, sl, data, len);
2262 w += sldns_str_print(s, sl, "no timeout value (only valid for client option) ");
2264 timeout = sldns_read_uint16(data);
2265 w += sldns_str_print(s, sl, "timeout value in units of 100ms %u", (int)timeout);
2270 int sldns_wire2str_edns_ede_print(char** s, size_t* sl,
2271 uint8_t* data, size_t len)
2275 sldns_lookup_table *lt;
2280 w += sldns_str_print(s, sl, "malformed ede ");
2281 w += print_hex_buf(s, sl, data, len);
2285 ede_code = sldns_read_uint16(data);
2286 lt = sldns_lookup_by_id(sldns_edns_ede_codes, (int)ede_code);
2288 w += sldns_str_print(s, sl, "%s", lt->name);
2289 else w += sldns_str_print(s, sl, "%d", (int)ede_code);
2294 w += sldns_str_print(s, sl, " ");
2296 /* If it looks like text, show it as text. */
2298 for(i=2; i<len; i++) {
2299 if(isprint((unsigned char)data[i]) || data[i] == '\t')
2305 w += sldns_str_print(s, sl, "\"");
2306 for(i=2; i<len; i++) {
2307 w += str_char_print(s, sl, data[i]);
2309 w += sldns_str_print(s, sl, "\"");
2311 w += print_hex_buf(s, sl, data+2, len-2);
2316 int sldns_wire2str_edns_option_print(char** s, size_t* sl,
2317 uint16_t option_code, uint8_t* optdata, size_t optlen)
2320 w += sldns_wire2str_edns_option_code_print(s, sl, option_code);
2321 w += sldns_str_print(s, sl, ": ");
2322 switch(option_code) {
2324 w += sldns_wire2str_edns_llq_print(s, sl, optdata, optlen);
2327 w += sldns_wire2str_edns_ul_print(s, sl, optdata, optlen);
2329 case LDNS_EDNS_NSID:
2330 w += sldns_wire2str_edns_nsid_print(s, sl, optdata, optlen);
2333 w += sldns_wire2str_edns_dau_print(s, sl, optdata, optlen);
2336 w += sldns_wire2str_edns_dhu_print(s, sl, optdata, optlen);
2339 w += sldns_wire2str_edns_n3u_print(s, sl, optdata, optlen);
2341 case LDNS_EDNS_CLIENT_SUBNET:
2342 w += sldns_wire2str_edns_subnet_print(s, sl, optdata, optlen);
2344 case LDNS_EDNS_KEEPALIVE:
2345 w += sldns_wire2str_edns_keepalive_print(s, sl, optdata, optlen);
2347 case LDNS_EDNS_PADDING:
2348 w += print_hex_buf(s, sl, optdata, optlen);
2351 w += sldns_wire2str_edns_ede_print(s, sl, optdata, optlen);
2354 /* unknown option code */
2355 w += print_hex_buf(s, sl, optdata, optlen);
2361 /** print the edns options to string */
2363 print_edns_opts(char** s, size_t* sl, uint8_t* rdata, size_t rdatalen)
2365 uint16_t option_code, option_len;
2367 while(rdatalen > 0) {
2370 w += sldns_str_print(s, sl, " ; malformed: ");
2371 w += print_hex_buf(s, sl, rdata, rdatalen);
2374 option_code = sldns_read_uint16(rdata);
2375 option_len = sldns_read_uint16(rdata+2);
2380 if(rdatalen < (size_t)option_len) {
2381 w += sldns_str_print(s, sl, " ; malformed ");
2382 w += sldns_wire2str_edns_option_code_print(s, sl,
2384 w += sldns_str_print(s, sl, ": ");
2385 w += print_hex_buf(s, sl, rdata, rdatalen);
2388 w += sldns_str_print(s, sl, " ; ");
2389 w += sldns_wire2str_edns_option_print(s, sl, option_code,
2391 rdata += option_len;
2392 rdatalen -= option_len;
2397 int sldns_wire2str_edns_scan(uint8_t** data, size_t* data_len, char** str,
2398 size_t* str_len, uint8_t* pkt, size_t pktlen)
2401 uint8_t ext_rcode, edns_version;
2402 uint16_t udpsize, edns_bits, rdatalen;
2403 w += sldns_str_print(str, str_len, "; EDNS:");
2405 /* some input checks, domain name */
2406 if(*data_len < 1+10)
2407 return w + print_remainder_hex("Error malformed 0x",
2408 data, data_len, str, str_len);
2410 return w + print_remainder_hex("Error nonrootdname 0x",
2411 data, data_len, str, str_len);
2416 /* check type and read fixed contents */
2417 if(sldns_read_uint16((*data)) != LDNS_RR_TYPE_OPT) {
2418 return w + print_remainder_hex("Error nottypeOPT 0x",
2419 data, data_len, str, str_len);
2421 udpsize = sldns_read_uint16((*data)+2);
2422 ext_rcode = (*data)[4];
2423 edns_version = (*data)[5];
2424 edns_bits = sldns_read_uint16((*data)+6);
2425 rdatalen = sldns_read_uint16((*data)+8);
2429 w += sldns_str_print(str, str_len, " version: %u;",
2430 (unsigned)edns_version);
2431 w += sldns_str_print(str, str_len, " flags:");
2432 if((edns_bits & LDNS_EDNS_MASK_DO_BIT))
2433 w += sldns_str_print(str, str_len, " do");
2434 /* the extended rcode is the value set, shifted four bits,
2435 * and or'd with the original rcode */
2437 int rc = ((int)ext_rcode)<<4;
2438 if(pkt && pktlen >= LDNS_HEADER_SIZE)
2439 rc |= LDNS_RCODE_WIRE(pkt);
2440 w += sldns_str_print(str, str_len, " ; ext-rcode: %d", rc);
2442 w += sldns_str_print(str, str_len, " ; udp: %u", (unsigned)udpsize);
2445 if((size_t)*data_len < rdatalen) {
2446 w += sldns_str_print(str, str_len,
2447 " ; Error EDNS rdata too short; ");
2448 rdatalen = (uint16_t)*data_len;
2450 w += print_edns_opts(str, str_len, *data, rdatalen);
2451 (*data) += rdatalen;
2452 (*data_len) -= rdatalen;
2454 w += sldns_str_print(str, str_len, "\n");