1fdfb4ba6Ssthen /* 2fdfb4ba6Ssthen * wire2str.c 3fdfb4ba6Ssthen * 4fdfb4ba6Ssthen * conversion routines from the wire format 5fdfb4ba6Ssthen * to the presentation format (strings) 6fdfb4ba6Ssthen * 7fdfb4ba6Ssthen * (c) NLnet Labs, 2004-2006 8fdfb4ba6Ssthen * 9fdfb4ba6Ssthen * See the file LICENSE for the license 10fdfb4ba6Ssthen */ 11fdfb4ba6Ssthen /** 12fdfb4ba6Ssthen * \file 13fdfb4ba6Ssthen * 14fdfb4ba6Ssthen * Contains functions to translate the wireformat to text 15fdfb4ba6Ssthen * representation, as well as functions to print them. 16fdfb4ba6Ssthen */ 17fdfb4ba6Ssthen #include "config.h" 18fdfb4ba6Ssthen #include "sldns/wire2str.h" 19fdfb4ba6Ssthen #include "sldns/str2wire.h" 20fdfb4ba6Ssthen #include "sldns/rrdef.h" 21fdfb4ba6Ssthen #include "sldns/pkthdr.h" 22fdfb4ba6Ssthen #include "sldns/parseutil.h" 23fdfb4ba6Ssthen #include "sldns/sbuffer.h" 24fdfb4ba6Ssthen #include "sldns/keyraw.h" 25ebf5bb73Ssthen #include "util/data/dname.h" 26fdfb4ba6Ssthen #ifdef HAVE_TIME_H 27fdfb4ba6Ssthen #include <time.h> 28fdfb4ba6Ssthen #endif 29fdfb4ba6Ssthen #include <sys/time.h> 30fdfb4ba6Ssthen #include <stdarg.h> 31fdfb4ba6Ssthen #include <ctype.h> 32fdfb4ba6Ssthen #ifdef HAVE_NETDB_H 33fdfb4ba6Ssthen #include <netdb.h> 34fdfb4ba6Ssthen #endif 35fdfb4ba6Ssthen 36fdfb4ba6Ssthen /* lookup tables for standard DNS stuff */ 37fdfb4ba6Ssthen /* Taken from RFC 2535, section 7. */ 38fdfb4ba6Ssthen static sldns_lookup_table sldns_algorithms_data[] = { 39fdfb4ba6Ssthen { LDNS_RSAMD5, "RSAMD5" }, 40fdfb4ba6Ssthen { LDNS_DH, "DH" }, 41fdfb4ba6Ssthen { LDNS_DSA, "DSA" }, 42fdfb4ba6Ssthen { LDNS_ECC, "ECC" }, 43fdfb4ba6Ssthen { LDNS_RSASHA1, "RSASHA1" }, 44fdfb4ba6Ssthen { LDNS_DSA_NSEC3, "DSA-NSEC3-SHA1" }, 45fdfb4ba6Ssthen { LDNS_RSASHA1_NSEC3, "RSASHA1-NSEC3-SHA1" }, 46fdfb4ba6Ssthen { LDNS_RSASHA256, "RSASHA256"}, 47fdfb4ba6Ssthen { LDNS_RSASHA512, "RSASHA512"}, 48fdfb4ba6Ssthen { LDNS_ECC_GOST, "ECC-GOST"}, 49fdfb4ba6Ssthen { LDNS_ECDSAP256SHA256, "ECDSAP256SHA256"}, 50fdfb4ba6Ssthen { LDNS_ECDSAP384SHA384, "ECDSAP384SHA384"}, 512be9e038Ssthen { LDNS_ED25519, "ED25519"}, 522be9e038Ssthen { LDNS_ED448, "ED448"}, 53fdfb4ba6Ssthen { LDNS_INDIRECT, "INDIRECT" }, 54fdfb4ba6Ssthen { LDNS_PRIVATEDNS, "PRIVATEDNS" }, 55fdfb4ba6Ssthen { LDNS_PRIVATEOID, "PRIVATEOID" }, 56fdfb4ba6Ssthen { 0, NULL } 57fdfb4ba6Ssthen }; 58fdfb4ba6Ssthen sldns_lookup_table* sldns_algorithms = sldns_algorithms_data; 59fdfb4ba6Ssthen 60fdfb4ba6Ssthen /* hash algorithms in DS record */ 61fdfb4ba6Ssthen static sldns_lookup_table sldns_hashes_data[] = { 62fdfb4ba6Ssthen { LDNS_SHA1, "SHA1" }, 63fdfb4ba6Ssthen { LDNS_SHA256, "SHA256" }, 64fdfb4ba6Ssthen { LDNS_HASH_GOST, "HASH-GOST" }, 65fdfb4ba6Ssthen { LDNS_SHA384, "SHA384" }, 66fdfb4ba6Ssthen { 0, NULL } 67fdfb4ba6Ssthen }; 68fdfb4ba6Ssthen sldns_lookup_table* sldns_hashes = sldns_hashes_data; 69fdfb4ba6Ssthen 70fdfb4ba6Ssthen /* Taken from RFC 4398 */ 71fdfb4ba6Ssthen static sldns_lookup_table sldns_cert_algorithms_data[] = { 72fdfb4ba6Ssthen { LDNS_CERT_PKIX, "PKIX" }, 73fdfb4ba6Ssthen { LDNS_CERT_SPKI, "SPKI" }, 74fdfb4ba6Ssthen { LDNS_CERT_PGP, "PGP" }, 75fdfb4ba6Ssthen { LDNS_CERT_IPKIX, "IPKIX" }, 76fdfb4ba6Ssthen { LDNS_CERT_ISPKI, "ISPKI" }, 77fdfb4ba6Ssthen { LDNS_CERT_IPGP, "IPGP" }, 78fdfb4ba6Ssthen { LDNS_CERT_ACPKIX, "ACPKIX" }, 79fdfb4ba6Ssthen { LDNS_CERT_IACPKIX, "IACPKIX" }, 80fdfb4ba6Ssthen { LDNS_CERT_URI, "URI" }, 81fdfb4ba6Ssthen { LDNS_CERT_OID, "OID" }, 82fdfb4ba6Ssthen { 0, NULL } 83fdfb4ba6Ssthen }; 84fdfb4ba6Ssthen sldns_lookup_table* sldns_cert_algorithms = sldns_cert_algorithms_data; 85fdfb4ba6Ssthen 86fdfb4ba6Ssthen /* if these are used elsewhere */ 87fdfb4ba6Ssthen static sldns_lookup_table sldns_rcodes_data[] = { 88fdfb4ba6Ssthen { LDNS_RCODE_NOERROR, "NOERROR" }, 89fdfb4ba6Ssthen { LDNS_RCODE_FORMERR, "FORMERR" }, 90fdfb4ba6Ssthen { LDNS_RCODE_SERVFAIL, "SERVFAIL" }, 91fdfb4ba6Ssthen { LDNS_RCODE_NXDOMAIN, "NXDOMAIN" }, 92fdfb4ba6Ssthen { LDNS_RCODE_NOTIMPL, "NOTIMPL" }, 93fdfb4ba6Ssthen { LDNS_RCODE_REFUSED, "REFUSED" }, 94fdfb4ba6Ssthen { LDNS_RCODE_YXDOMAIN, "YXDOMAIN" }, 95fdfb4ba6Ssthen { LDNS_RCODE_YXRRSET, "YXRRSET" }, 96fdfb4ba6Ssthen { LDNS_RCODE_NXRRSET, "NXRRSET" }, 97fdfb4ba6Ssthen { LDNS_RCODE_NOTAUTH, "NOTAUTH" }, 98fdfb4ba6Ssthen { LDNS_RCODE_NOTZONE, "NOTZONE" }, 99fdfb4ba6Ssthen { 0, NULL } 100fdfb4ba6Ssthen }; 101fdfb4ba6Ssthen sldns_lookup_table* sldns_rcodes = sldns_rcodes_data; 102fdfb4ba6Ssthen 103fdfb4ba6Ssthen static sldns_lookup_table sldns_opcodes_data[] = { 104fdfb4ba6Ssthen { LDNS_PACKET_QUERY, "QUERY" }, 105fdfb4ba6Ssthen { LDNS_PACKET_IQUERY, "IQUERY" }, 106fdfb4ba6Ssthen { LDNS_PACKET_STATUS, "STATUS" }, 107fdfb4ba6Ssthen { LDNS_PACKET_NOTIFY, "NOTIFY" }, 108fdfb4ba6Ssthen { LDNS_PACKET_UPDATE, "UPDATE" }, 109fdfb4ba6Ssthen { 0, NULL } 110fdfb4ba6Ssthen }; 111fdfb4ba6Ssthen sldns_lookup_table* sldns_opcodes = sldns_opcodes_data; 112fdfb4ba6Ssthen 113fdfb4ba6Ssthen static sldns_lookup_table sldns_wireparse_errors_data[] = { 114fdfb4ba6Ssthen { LDNS_WIREPARSE_ERR_OK, "no parse error" }, 115fdfb4ba6Ssthen { LDNS_WIREPARSE_ERR_GENERAL, "parse error" }, 116fdfb4ba6Ssthen { LDNS_WIREPARSE_ERR_DOMAINNAME_OVERFLOW, "Domainname length overflow" }, 117fdfb4ba6Ssthen { LDNS_WIREPARSE_ERR_DOMAINNAME_UNDERFLOW, "Domainname length underflow (zero length)" }, 118fdfb4ba6Ssthen { LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, "buffer too small" }, 119fdfb4ba6Ssthen { LDNS_WIREPARSE_ERR_LABEL_OVERFLOW, "Label length overflow" }, 120fdfb4ba6Ssthen { LDNS_WIREPARSE_ERR_EMPTY_LABEL, "Empty label" }, 121fdfb4ba6Ssthen { LDNS_WIREPARSE_ERR_SYNTAX_BAD_ESCAPE, "Syntax error, bad escape sequence" }, 122fdfb4ba6Ssthen { LDNS_WIREPARSE_ERR_SYNTAX, "Syntax error, could not parse the RR" }, 123fdfb4ba6Ssthen { LDNS_WIREPARSE_ERR_SYNTAX_TTL, "Syntax error, could not parse the RR's TTL" }, 124fdfb4ba6Ssthen { LDNS_WIREPARSE_ERR_SYNTAX_TYPE, "Syntax error, could not parse the RR's type" }, 125fdfb4ba6Ssthen { LDNS_WIREPARSE_ERR_SYNTAX_CLASS, "Syntax error, could not parse the RR's class" }, 126fdfb4ba6Ssthen { LDNS_WIREPARSE_ERR_SYNTAX_RDATA, "Syntax error, could not parse the RR's rdata" }, 127fdfb4ba6Ssthen { LDNS_WIREPARSE_ERR_SYNTAX_MISSING_VALUE, "Syntax error, value expected" }, 128fdfb4ba6Ssthen { LDNS_WIREPARSE_ERR_INVALID_STR, "Conversion error, string expected" }, 129fdfb4ba6Ssthen { LDNS_WIREPARSE_ERR_SYNTAX_B64, "Conversion error, b64 encoding expected" }, 130fdfb4ba6Ssthen { LDNS_WIREPARSE_ERR_SYNTAX_B32_EXT, "Conversion error, b32 ext encoding expected" }, 131fdfb4ba6Ssthen { LDNS_WIREPARSE_ERR_SYNTAX_HEX, "Conversion error, hex encoding expected" }, 132fdfb4ba6Ssthen { LDNS_WIREPARSE_ERR_CERT_BAD_ALGORITHM, "Bad algorithm type for CERT record" }, 133fdfb4ba6Ssthen { LDNS_WIREPARSE_ERR_SYNTAX_TIME, "Conversion error, time encoding expected" }, 134fdfb4ba6Ssthen { LDNS_WIREPARSE_ERR_SYNTAX_PERIOD, "Conversion error, time period encoding expected" }, 135fdfb4ba6Ssthen { LDNS_WIREPARSE_ERR_SYNTAX_ILNP64, "Conversion error, 4 colon separated hex numbers expected" }, 136fdfb4ba6Ssthen { LDNS_WIREPARSE_ERR_SYNTAX_EUI48, 137fdfb4ba6Ssthen "Conversion error, 6 two character hex numbers " 138fdfb4ba6Ssthen "separated by dashes expected (i.e. xx-xx-xx-xx-xx-xx" }, 139fdfb4ba6Ssthen { LDNS_WIREPARSE_ERR_SYNTAX_EUI64, 140fdfb4ba6Ssthen "Conversion error, 8 two character hex numbers " 141fdfb4ba6Ssthen "separated by dashes expected (i.e. xx-xx-xx-xx-xx-xx-xx-xx" }, 142fdfb4ba6Ssthen { LDNS_WIREPARSE_ERR_SYNTAX_TAG, 143fdfb4ba6Ssthen "Conversion error, a non-zero sequence of US-ASCII letters " 144fdfb4ba6Ssthen "and numbers in lower case expected" }, 145fdfb4ba6Ssthen { LDNS_WIREPARSE_ERR_NOT_IMPL, "not implemented" }, 146fdfb4ba6Ssthen { LDNS_WIREPARSE_ERR_SYNTAX_INT, "Conversion error, integer expected" }, 147fdfb4ba6Ssthen { LDNS_WIREPARSE_ERR_SYNTAX_IP4, "Conversion error, ip4 addr expected" }, 148fdfb4ba6Ssthen { LDNS_WIREPARSE_ERR_SYNTAX_IP6, "Conversion error, ip6 addr expected" }, 149fdfb4ba6Ssthen { LDNS_WIREPARSE_ERR_SYNTAX_INTEGER_OVERFLOW, "Syntax error, integer overflow" }, 150fdfb4ba6Ssthen { LDNS_WIREPARSE_ERR_INCLUDE, "$INCLUDE directive was seen in the zone" }, 151fdfb4ba6Ssthen { LDNS_WIREPARSE_ERR_PARENTHESIS, "Parse error, parenthesis mismatch" }, 152191f22c6Ssthen { LDNS_WIREPARSE_ERR_SVCB_UNKNOWN_KEY, "Unknown SvcParamKey"}, 153191f22c6Ssthen { LDNS_WIREPARSE_ERR_SVCB_MISSING_PARAM, "SvcParam is missing a SvcParamValue"}, 154191f22c6Ssthen { LDNS_WIREPARSE_ERR_SVCB_DUPLICATE_KEYS, "Duplicate SVCB key found"}, 155191f22c6Ssthen { LDNS_WIREPARSE_ERR_SVCB_MANDATORY_TOO_MANY_KEYS, "Too many keys in mandatory" }, 156191f22c6Ssthen { LDNS_WIREPARSE_ERR_SVCB_TOO_MANY_PARAMS, 157191f22c6Ssthen "Too many SvcParams. Unbound only allows 63 entries" }, 158191f22c6Ssthen { LDNS_WIREPARSE_ERR_SVCB_MANDATORY_MISSING_PARAM, 159191f22c6Ssthen "Mandatory SvcParamKey is missing"}, 160191f22c6Ssthen { LDNS_WIREPARSE_ERR_SVCB_MANDATORY_DUPLICATE_KEY, 161191f22c6Ssthen "Keys in SvcParam mandatory MUST be unique" }, 162191f22c6Ssthen { LDNS_WIREPARSE_ERR_SVCB_MANDATORY_IN_MANDATORY, 163191f22c6Ssthen "mandatory MUST not be included as mandatory parameter" }, 164191f22c6Ssthen { LDNS_WIREPARSE_ERR_SVCB_PORT_VALUE_SYNTAX, 165191f22c6Ssthen "Could not parse port SvcParamValue" }, 166191f22c6Ssthen { LDNS_WIREPARSE_ERR_SVCB_IPV4_TOO_MANY_ADDRESSES, 167191f22c6Ssthen "Too many IPv4 addresses in ipv4hint" }, 168191f22c6Ssthen { LDNS_WIREPARSE_ERR_SVCB_IPV6_TOO_MANY_ADDRESSES, 169191f22c6Ssthen "Too many IPv6 addresses in ipv6hint" }, 170191f22c6Ssthen { LDNS_WIREPARSE_ERR_SVCB_ALPN_KEY_TOO_LARGE, 171191f22c6Ssthen "Alpn strings need to be smaller than 255 chars"}, 172191f22c6Ssthen { LDNS_WIREPARSE_ERR_SVCB_NO_DEFAULT_ALPN_VALUE, 173191f22c6Ssthen "No-default-alpn should not have a value" }, 174191f22c6Ssthen { LDNS_WIREPARSE_ERR_SVCPARAM_BROKEN_RDATA, 175191f22c6Ssthen "General SVCParam error" }, 176fdfb4ba6Ssthen { 0, NULL } 177fdfb4ba6Ssthen }; 178fdfb4ba6Ssthen sldns_lookup_table* sldns_wireparse_errors = sldns_wireparse_errors_data; 179fdfb4ba6Ssthen 180fdfb4ba6Ssthen static sldns_lookup_table sldns_edns_flags_data[] = { 181fdfb4ba6Ssthen { 3600, "do"}, 182fdfb4ba6Ssthen { 0, NULL} 183fdfb4ba6Ssthen }; 184fdfb4ba6Ssthen sldns_lookup_table* sldns_edns_flags = sldns_edns_flags_data; 185fdfb4ba6Ssthen 186fdfb4ba6Ssthen static sldns_lookup_table sldns_edns_options_data[] = { 187fdfb4ba6Ssthen { 1, "LLQ" }, 188fdfb4ba6Ssthen { 2, "UL" }, 189fdfb4ba6Ssthen { 3, "NSID" }, 190fdfb4ba6Ssthen /* 4 draft-cheshire-edns0-owner-option */ 191fdfb4ba6Ssthen { 5, "DAU" }, 192fdfb4ba6Ssthen { 6, "DHU" }, 193fdfb4ba6Ssthen { 7, "N3U" }, 194fdfb4ba6Ssthen { 8, "edns-client-subnet" }, 195d896b962Ssthen { 10, "COOKIE" }, 1962be9e038Ssthen { 11, "edns-tcp-keepalive"}, 1972ee382b6Ssthen { 12, "Padding" }, 1980bdb4f62Ssthen { 15, "EDE"}, 199fdfb4ba6Ssthen { 0, NULL} 200fdfb4ba6Ssthen }; 201fdfb4ba6Ssthen sldns_lookup_table* sldns_edns_options = sldns_edns_options_data; 202fdfb4ba6Ssthen 203d896b962Ssthen /* From RFC8914 5.2 Table 3, the "Extended DNS Error Codes" registry. */ 204d896b962Ssthen static sldns_lookup_table sldns_edns_ede_codes_data[] = { 205d896b962Ssthen { LDNS_EDE_NONE, "None" }, 206d896b962Ssthen { LDNS_EDE_OTHER, "Other Error" }, 207d896b962Ssthen { LDNS_EDE_UNSUPPORTED_DNSKEY_ALG, "Unsupported DNSKEY Algorithm" }, 208d896b962Ssthen { LDNS_EDE_UNSUPPORTED_DS_DIGEST, "Unsupported DS Digest Type" }, 209d896b962Ssthen { LDNS_EDE_STALE_ANSWER, "Stale Answer" }, 210d896b962Ssthen { LDNS_EDE_FORGED_ANSWER, "Forged Answer" }, 211d896b962Ssthen { LDNS_EDE_DNSSEC_INDETERMINATE, "DNSSEC Indeterminate" }, 212d896b962Ssthen { LDNS_EDE_DNSSEC_BOGUS, "DNSSEC Bogus" }, 213d896b962Ssthen { LDNS_EDE_SIGNATURE_EXPIRED, "Signature Expired" }, 214d896b962Ssthen { LDNS_EDE_SIGNATURE_NOT_YET_VALID, "Signature Not Yet Valid" }, 215d896b962Ssthen { LDNS_EDE_DNSKEY_MISSING, "DNSKEY Missing" }, 216d896b962Ssthen { LDNS_EDE_RRSIGS_MISSING, "RRSIGs Missing" }, 217d896b962Ssthen { LDNS_EDE_NO_ZONE_KEY_BIT_SET, "No Zone Key Bit Set" }, 218d896b962Ssthen { LDNS_EDE_NSEC_MISSING, "NSEC Missing" }, 219d896b962Ssthen { LDNS_EDE_CACHED_ERROR, "Cached Error" }, 220d896b962Ssthen { LDNS_EDE_NOT_READY, "Not Ready" }, 221d896b962Ssthen { LDNS_EDE_BLOCKED, "Blocked" }, 222d896b962Ssthen { LDNS_EDE_CENSORED, "Censored" }, 223d896b962Ssthen { LDNS_EDE_FILTERED, "Filtered" }, 224d896b962Ssthen { LDNS_EDE_PROHIBITED, "Prohibited" }, 225d896b962Ssthen { LDNS_EDE_STALE_NXDOMAIN_ANSWER, "Stale NXDOMAIN Answer" }, 226d896b962Ssthen { LDNS_EDE_NOT_AUTHORITATIVE, "Not Authoritative" }, 227d896b962Ssthen { LDNS_EDE_NOT_SUPPORTED, "Not Supported" }, 228d896b962Ssthen { LDNS_EDE_NO_REACHABLE_AUTHORITY, "No Reachable Authority" }, 229d896b962Ssthen { LDNS_EDE_NETWORK_ERROR, "Network Error" }, 230d896b962Ssthen { LDNS_EDE_INVALID_DATA, "Invalid Data" }, 231*98bc733bSsthen { LDNS_EDE_SIGNATURE_EXPIRED_BEFORE_VALID, "Signature Expired Before Valid" }, 232*98bc733bSsthen { LDNS_EDE_TOO_EARLY, "Non-Replayable Transactions Received in 0-RTT Data" }, 233*98bc733bSsthen { LDNS_EDE_UNSUPPORTED_NSEC3_ITERATIONS, "Unsupported NSEC3 Iterations Value" }, 234*98bc733bSsthen { LDNS_EDE_BADPROXYPOLICY, "Unable to Conform to Policy" }, 235*98bc733bSsthen { LDNS_EDE_SYNTHESIZED, "Synthesized Answer" }, 236d896b962Ssthen { 0, NULL} 237d896b962Ssthen }; 238d896b962Ssthen sldns_lookup_table* sldns_edns_ede_codes = sldns_edns_ede_codes_data; 239d896b962Ssthen 2402be9e038Ssthen static sldns_lookup_table sldns_tsig_errors_data[] = { 2412be9e038Ssthen { LDNS_TSIG_ERROR_NOERROR, "NOERROR" }, 2422be9e038Ssthen { LDNS_RCODE_FORMERR, "FORMERR" }, 2432be9e038Ssthen { LDNS_RCODE_SERVFAIL, "SERVFAIL" }, 2442be9e038Ssthen { LDNS_RCODE_NXDOMAIN, "NXDOMAIN" }, 2452be9e038Ssthen { LDNS_RCODE_NOTIMPL, "NOTIMPL" }, 2462be9e038Ssthen { LDNS_RCODE_REFUSED, "REFUSED" }, 2472be9e038Ssthen { LDNS_RCODE_YXDOMAIN, "YXDOMAIN" }, 2482be9e038Ssthen { LDNS_RCODE_YXRRSET, "YXRRSET" }, 2492be9e038Ssthen { LDNS_RCODE_NXRRSET, "NXRRSET" }, 2502be9e038Ssthen { LDNS_RCODE_NOTAUTH, "NOTAUTH" }, 2512be9e038Ssthen { LDNS_RCODE_NOTZONE, "NOTZONE" }, 2522be9e038Ssthen { LDNS_TSIG_ERROR_BADSIG, "BADSIG" }, 2532be9e038Ssthen { LDNS_TSIG_ERROR_BADKEY, "BADKEY" }, 2542be9e038Ssthen { LDNS_TSIG_ERROR_BADTIME, "BADTIME" }, 2552be9e038Ssthen { LDNS_TSIG_ERROR_BADMODE, "BADMODE" }, 2562be9e038Ssthen { LDNS_TSIG_ERROR_BADNAME, "BADNAME" }, 2572be9e038Ssthen { LDNS_TSIG_ERROR_BADALG, "BADALG" }, 2582be9e038Ssthen { 0, NULL } 2592be9e038Ssthen }; 2602be9e038Ssthen sldns_lookup_table* sldns_tsig_errors = sldns_tsig_errors_data; 2612be9e038Ssthen 262191f22c6Ssthen /* draft-ietf-dnsop-svcb-https-06: 6. Initial SvcParamKeys */ 263191f22c6Ssthen const char *svcparamkey_strs[] = { 264191f22c6Ssthen "mandatory", "alpn", "no-default-alpn", "port", 2658b7325afSsthen "ipv4hint", "ech", "ipv6hint", "dohpath" 266191f22c6Ssthen }; 267191f22c6Ssthen 268fdfb4ba6Ssthen char* sldns_wire2str_pkt(uint8_t* data, size_t len) 269fdfb4ba6Ssthen { 270fdfb4ba6Ssthen size_t slen = (size_t)sldns_wire2str_pkt_buf(data, len, NULL, 0); 271fdfb4ba6Ssthen char* result = (char*)malloc(slen+1); 272fdfb4ba6Ssthen if(!result) return NULL; 273fdfb4ba6Ssthen sldns_wire2str_pkt_buf(data, len, result, slen+1); 274fdfb4ba6Ssthen return result; 275fdfb4ba6Ssthen } 276fdfb4ba6Ssthen 277fdfb4ba6Ssthen char* sldns_wire2str_rr(uint8_t* rr, size_t len) 278fdfb4ba6Ssthen { 279fdfb4ba6Ssthen size_t slen = (size_t)sldns_wire2str_rr_buf(rr, len, NULL, 0); 280fdfb4ba6Ssthen char* result = (char*)malloc(slen+1); 281fdfb4ba6Ssthen if(!result) return NULL; 282fdfb4ba6Ssthen sldns_wire2str_rr_buf(rr, len, result, slen+1); 283fdfb4ba6Ssthen return result; 284fdfb4ba6Ssthen } 285fdfb4ba6Ssthen 286fdfb4ba6Ssthen char* sldns_wire2str_type(uint16_t rrtype) 287fdfb4ba6Ssthen { 288fdfb4ba6Ssthen char buf[16]; 289fdfb4ba6Ssthen sldns_wire2str_type_buf(rrtype, buf, sizeof(buf)); 290fdfb4ba6Ssthen return strdup(buf); 291fdfb4ba6Ssthen } 292fdfb4ba6Ssthen 293fdfb4ba6Ssthen char* sldns_wire2str_class(uint16_t rrclass) 294fdfb4ba6Ssthen { 295fdfb4ba6Ssthen char buf[16]; 296fdfb4ba6Ssthen sldns_wire2str_class_buf(rrclass, buf, sizeof(buf)); 297fdfb4ba6Ssthen return strdup(buf); 298fdfb4ba6Ssthen } 299fdfb4ba6Ssthen 300fdfb4ba6Ssthen char* sldns_wire2str_dname(uint8_t* dname, size_t dname_len) 301fdfb4ba6Ssthen { 302fdfb4ba6Ssthen size_t slen=(size_t)sldns_wire2str_dname_buf(dname, dname_len, NULL, 0); 303fdfb4ba6Ssthen char* result = (char*)malloc(slen+1); 304fdfb4ba6Ssthen if(!result) return NULL; 305fdfb4ba6Ssthen sldns_wire2str_dname_buf(dname, dname_len, result, slen+1); 306fdfb4ba6Ssthen return result; 307fdfb4ba6Ssthen } 308fdfb4ba6Ssthen 309fdfb4ba6Ssthen char* sldns_wire2str_rcode(int rcode) 310fdfb4ba6Ssthen { 311fdfb4ba6Ssthen char buf[16]; 312fdfb4ba6Ssthen sldns_wire2str_rcode_buf(rcode, buf, sizeof(buf)); 313fdfb4ba6Ssthen return strdup(buf); 314fdfb4ba6Ssthen } 315fdfb4ba6Ssthen 316fdfb4ba6Ssthen int sldns_wire2str_pkt_buf(uint8_t* d, size_t dlen, char* s, size_t slen) 317fdfb4ba6Ssthen { 318fdfb4ba6Ssthen /* use arguments as temporary variables */ 319fdfb4ba6Ssthen return sldns_wire2str_pkt_scan(&d, &dlen, &s, &slen); 320fdfb4ba6Ssthen } 321fdfb4ba6Ssthen 322fdfb4ba6Ssthen int sldns_wire2str_rr_buf(uint8_t* d, size_t dlen, char* s, size_t slen) 323fdfb4ba6Ssthen { 324fdfb4ba6Ssthen /* use arguments as temporary variables */ 325ebf5bb73Ssthen return sldns_wire2str_rr_scan(&d, &dlen, &s, &slen, NULL, 0, NULL); 326fdfb4ba6Ssthen } 327fdfb4ba6Ssthen 328938a3a5eSflorian int sldns_wire2str_rrquestion_buf(uint8_t* d, size_t dlen, char* s, size_t slen) 329938a3a5eSflorian { 330938a3a5eSflorian /* use arguments as temporary variables */ 331ebf5bb73Ssthen return sldns_wire2str_rrquestion_scan(&d, &dlen, &s, &slen, NULL, 0, NULL); 332938a3a5eSflorian } 333938a3a5eSflorian 334fdfb4ba6Ssthen int sldns_wire2str_rdata_buf(uint8_t* rdata, size_t rdata_len, char* str, 335fdfb4ba6Ssthen size_t str_len, uint16_t rrtype) 336fdfb4ba6Ssthen { 337fdfb4ba6Ssthen /* use arguments as temporary variables */ 338fdfb4ba6Ssthen return sldns_wire2str_rdata_scan(&rdata, &rdata_len, &str, &str_len, 339ebf5bb73Ssthen rrtype, NULL, 0, NULL); 340fdfb4ba6Ssthen } 341fdfb4ba6Ssthen 342fdfb4ba6Ssthen int sldns_wire2str_rr_unknown_buf(uint8_t* d, size_t dlen, char* s, size_t slen) 343fdfb4ba6Ssthen { 344fdfb4ba6Ssthen /* use arguments as temporary variables */ 345ebf5bb73Ssthen return sldns_wire2str_rr_unknown_scan(&d, &dlen, &s, &slen, NULL, 0, NULL); 346fdfb4ba6Ssthen } 347fdfb4ba6Ssthen 348fdfb4ba6Ssthen int sldns_wire2str_rr_comment_buf(uint8_t* rr, size_t rrlen, size_t dname_len, 349fdfb4ba6Ssthen char* s, size_t slen) 350fdfb4ba6Ssthen { 351fdfb4ba6Ssthen uint16_t rrtype = sldns_wirerr_get_type(rr, rrlen, dname_len); 352fdfb4ba6Ssthen return sldns_wire2str_rr_comment_print(&s, &slen, rr, rrlen, dname_len, 353fdfb4ba6Ssthen rrtype); 354fdfb4ba6Ssthen } 355fdfb4ba6Ssthen 356fdfb4ba6Ssthen int sldns_wire2str_type_buf(uint16_t rrtype, char* s, size_t slen) 357fdfb4ba6Ssthen { 358fdfb4ba6Ssthen /* use arguments as temporary variables */ 359fdfb4ba6Ssthen return sldns_wire2str_type_print(&s, &slen, rrtype); 360fdfb4ba6Ssthen } 361fdfb4ba6Ssthen 362fdfb4ba6Ssthen int sldns_wire2str_class_buf(uint16_t rrclass, char* s, size_t slen) 363fdfb4ba6Ssthen { 364fdfb4ba6Ssthen /* use arguments as temporary variables */ 365fdfb4ba6Ssthen return sldns_wire2str_class_print(&s, &slen, rrclass); 366fdfb4ba6Ssthen } 367fdfb4ba6Ssthen 368fdfb4ba6Ssthen int sldns_wire2str_rcode_buf(int rcode, char* s, size_t slen) 369fdfb4ba6Ssthen { 370fdfb4ba6Ssthen /* use arguments as temporary variables */ 371fdfb4ba6Ssthen return sldns_wire2str_rcode_print(&s, &slen, rcode); 372fdfb4ba6Ssthen } 373fdfb4ba6Ssthen 3742be9e038Ssthen int sldns_wire2str_opcode_buf(int opcode, char* s, size_t slen) 3752be9e038Ssthen { 3762be9e038Ssthen /* use arguments as temporary variables */ 3772be9e038Ssthen return sldns_wire2str_opcode_print(&s, &slen, opcode); 3782be9e038Ssthen } 3792be9e038Ssthen 380fdfb4ba6Ssthen int sldns_wire2str_dname_buf(uint8_t* d, size_t dlen, char* s, size_t slen) 381fdfb4ba6Ssthen { 382fdfb4ba6Ssthen /* use arguments as temporary variables */ 383ebf5bb73Ssthen return sldns_wire2str_dname_scan(&d, &dlen, &s, &slen, NULL, 0, NULL); 384fdfb4ba6Ssthen } 385fdfb4ba6Ssthen 386fdfb4ba6Ssthen int sldns_str_vprint(char** str, size_t* slen, const char* format, va_list args) 387fdfb4ba6Ssthen { 388fdfb4ba6Ssthen int w = vsnprintf(*str, *slen, format, args); 389fdfb4ba6Ssthen if(w < 0) { 390fdfb4ba6Ssthen /* error in printout */ 391fdfb4ba6Ssthen return 0; 392fdfb4ba6Ssthen } else if((size_t)w >= *slen) { 393fdfb4ba6Ssthen *str = NULL; /* we do not want str to point outside of buffer*/ 394fdfb4ba6Ssthen *slen = 0; 395fdfb4ba6Ssthen } else { 396fdfb4ba6Ssthen *str += w; 397fdfb4ba6Ssthen *slen -= w; 398fdfb4ba6Ssthen } 399fdfb4ba6Ssthen return w; 400fdfb4ba6Ssthen } 401fdfb4ba6Ssthen 402fdfb4ba6Ssthen int sldns_str_print(char** str, size_t* slen, const char* format, ...) 403fdfb4ba6Ssthen { 404fdfb4ba6Ssthen int w; 405fdfb4ba6Ssthen va_list args; 406fdfb4ba6Ssthen va_start(args, format); 407fdfb4ba6Ssthen w = sldns_str_vprint(str, slen, format, args); 408fdfb4ba6Ssthen va_end(args); 409fdfb4ba6Ssthen return w; 410fdfb4ba6Ssthen } 411fdfb4ba6Ssthen 412fdfb4ba6Ssthen /** print hex format into text buffer for specified length */ 413fdfb4ba6Ssthen static int print_hex_buf(char** s, size_t* slen, uint8_t* buf, size_t len) 414fdfb4ba6Ssthen { 415fdfb4ba6Ssthen const char* hex = "0123456789ABCDEF"; 416fdfb4ba6Ssthen size_t i; 417fdfb4ba6Ssthen for(i=0; i<len; i++) { 418fdfb4ba6Ssthen (void)sldns_str_print(s, slen, "%c%c", hex[(buf[i]&0xf0)>>4], 419fdfb4ba6Ssthen hex[buf[i]&0x0f]); 420fdfb4ba6Ssthen } 421fdfb4ba6Ssthen return (int)len*2; 422fdfb4ba6Ssthen } 423fdfb4ba6Ssthen 424fdfb4ba6Ssthen /** print remainder of buffer in hex format with prefixed text */ 425fdfb4ba6Ssthen static int print_remainder_hex(const char* pref, uint8_t** d, size_t* dlen, 426fdfb4ba6Ssthen char** s, size_t* slen) 427fdfb4ba6Ssthen { 428fdfb4ba6Ssthen int w = 0; 429fdfb4ba6Ssthen w += sldns_str_print(s, slen, "%s", pref); 430fdfb4ba6Ssthen w += print_hex_buf(s, slen, *d, *dlen); 431fdfb4ba6Ssthen *d += *dlen; 432fdfb4ba6Ssthen *dlen = 0; 433fdfb4ba6Ssthen return w; 434fdfb4ba6Ssthen } 435fdfb4ba6Ssthen 436fdfb4ba6Ssthen int sldns_wire2str_pkt_scan(uint8_t** d, size_t* dlen, char** s, size_t* slen) 437fdfb4ba6Ssthen { 438ebf5bb73Ssthen int w = 0, comprloop = 0; 439fdfb4ba6Ssthen unsigned qdcount, ancount, nscount, arcount, i; 440fdfb4ba6Ssthen uint8_t* pkt = *d; 441fdfb4ba6Ssthen size_t pktlen = *dlen; 442fdfb4ba6Ssthen if(*dlen >= LDNS_HEADER_SIZE) { 443fdfb4ba6Ssthen qdcount = (unsigned)LDNS_QDCOUNT(*d); 444fdfb4ba6Ssthen ancount = (unsigned)LDNS_ANCOUNT(*d); 445fdfb4ba6Ssthen nscount = (unsigned)LDNS_NSCOUNT(*d); 446fdfb4ba6Ssthen arcount = (unsigned)LDNS_ARCOUNT(*d); 447fdfb4ba6Ssthen } else { 448fdfb4ba6Ssthen qdcount = ancount = nscount = arcount = 0; 449fdfb4ba6Ssthen } 450fdfb4ba6Ssthen w += sldns_wire2str_header_scan(d, dlen, s, slen); 451fdfb4ba6Ssthen w += sldns_str_print(s, slen, "\n"); 452fdfb4ba6Ssthen w += sldns_str_print(s, slen, ";; QUESTION SECTION:\n"); 453fdfb4ba6Ssthen for(i=0; i<qdcount; i++) { 454fdfb4ba6Ssthen w += sldns_wire2str_rrquestion_scan(d, dlen, s, slen, 455ebf5bb73Ssthen pkt, pktlen, &comprloop); 456fdfb4ba6Ssthen if(!*dlen) break; 457fdfb4ba6Ssthen } 458fdfb4ba6Ssthen w += sldns_str_print(s, slen, "\n"); 459fdfb4ba6Ssthen w += sldns_str_print(s, slen, ";; ANSWER SECTION:\n"); 460fdfb4ba6Ssthen for(i=0; i<ancount; i++) { 461ebf5bb73Ssthen w += sldns_wire2str_rr_scan(d, dlen, s, slen, pkt, pktlen, &comprloop); 462fdfb4ba6Ssthen if(!*dlen) break; 463fdfb4ba6Ssthen } 464fdfb4ba6Ssthen w += sldns_str_print(s, slen, "\n"); 465fdfb4ba6Ssthen w += sldns_str_print(s, slen, ";; AUTHORITY SECTION:\n"); 466fdfb4ba6Ssthen for(i=0; i<nscount; i++) { 467ebf5bb73Ssthen w += sldns_wire2str_rr_scan(d, dlen, s, slen, pkt, pktlen, &comprloop); 468fdfb4ba6Ssthen if(!*dlen) break; 469fdfb4ba6Ssthen } 470fdfb4ba6Ssthen w += sldns_str_print(s, slen, "\n"); 471fdfb4ba6Ssthen w += sldns_str_print(s, slen, ";; ADDITIONAL SECTION:\n"); 472fdfb4ba6Ssthen for(i=0; i<arcount; i++) { 473ebf5bb73Ssthen w += sldns_wire2str_rr_scan(d, dlen, s, slen, pkt, pktlen, &comprloop); 474fdfb4ba6Ssthen if(!*dlen) break; 475fdfb4ba6Ssthen } 476fdfb4ba6Ssthen /* other fields: WHEN(time), SERVER(IP) not available here. */ 477fdfb4ba6Ssthen w += sldns_str_print(s, slen, ";; MSG SIZE rcvd: %d\n", (int)pktlen); 478fdfb4ba6Ssthen if(*dlen > 0) { 479fdfb4ba6Ssthen w += print_remainder_hex(";; trailing garbage 0x", 480fdfb4ba6Ssthen d, dlen, s, slen); 481fdfb4ba6Ssthen w += sldns_str_print(s, slen, "\n"); 482fdfb4ba6Ssthen } 483fdfb4ba6Ssthen return w; 484fdfb4ba6Ssthen } 485fdfb4ba6Ssthen 486fdfb4ba6Ssthen /** scan type, class and ttl and printout, for rr */ 487fdfb4ba6Ssthen static int sldns_rr_tcttl_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) 488fdfb4ba6Ssthen { 489fdfb4ba6Ssthen int w = 0; 490fdfb4ba6Ssthen uint16_t t, c; 491fdfb4ba6Ssthen uint32_t ttl; 492fdfb4ba6Ssthen if(*dl < 8) { 493fdfb4ba6Ssthen if(*dl < 4) 494fdfb4ba6Ssthen return w + print_remainder_hex("; Error malformed 0x", 495fdfb4ba6Ssthen d, dl, s, sl); 496fdfb4ba6Ssthen /* these print values or 0x.. if none left */ 497fdfb4ba6Ssthen t = sldns_read_uint16(*d); 498fdfb4ba6Ssthen c = sldns_read_uint16((*d)+2); 499fdfb4ba6Ssthen (*d)+=4; 500fdfb4ba6Ssthen (*dl)-=4; 501fdfb4ba6Ssthen w += sldns_wire2str_class_print(s, sl, c); 502fdfb4ba6Ssthen w += sldns_str_print(s, sl, "\t"); 503fdfb4ba6Ssthen w += sldns_wire2str_type_print(s, sl, t); 504fdfb4ba6Ssthen if(*dl == 0) 505fdfb4ba6Ssthen return w + sldns_str_print(s, sl, "; Error no ttl"); 506fdfb4ba6Ssthen return w + print_remainder_hex( 507fdfb4ba6Ssthen "; Error malformed ttl 0x", d, dl, s, sl); 508fdfb4ba6Ssthen } 509fdfb4ba6Ssthen t = sldns_read_uint16(*d); 510fdfb4ba6Ssthen c = sldns_read_uint16((*d)+2); 511fdfb4ba6Ssthen ttl = sldns_read_uint32((*d)+4); 512fdfb4ba6Ssthen (*d)+=8; 513fdfb4ba6Ssthen (*dl)-=8; 514fdfb4ba6Ssthen w += sldns_str_print(s, sl, "%lu\t", (unsigned long)ttl); 515fdfb4ba6Ssthen w += sldns_wire2str_class_print(s, sl, c); 516fdfb4ba6Ssthen w += sldns_str_print(s, sl, "\t"); 517fdfb4ba6Ssthen w += sldns_wire2str_type_print(s, sl, t); 518fdfb4ba6Ssthen return w; 519fdfb4ba6Ssthen } 520fdfb4ba6Ssthen 521fdfb4ba6Ssthen int sldns_wire2str_rr_scan(uint8_t** d, size_t* dlen, char** s, size_t* slen, 522ebf5bb73Ssthen uint8_t* pkt, size_t pktlen, int* comprloop) 523fdfb4ba6Ssthen { 524fdfb4ba6Ssthen int w = 0; 525fdfb4ba6Ssthen uint8_t* rr = *d; 526fdfb4ba6Ssthen size_t rrlen = *dlen, dname_off, rdlen, ordlen; 527fdfb4ba6Ssthen uint16_t rrtype = 0; 528fdfb4ba6Ssthen 529fdfb4ba6Ssthen if(*dlen >= 3 && (*d)[0]==0 && 530fdfb4ba6Ssthen sldns_read_uint16((*d)+1)==LDNS_RR_TYPE_OPT) { 531fdfb4ba6Ssthen /* perform EDNS OPT processing */ 532fdfb4ba6Ssthen return sldns_wire2str_edns_scan(d, dlen, s, slen, pkt, pktlen); 533fdfb4ba6Ssthen } 534fdfb4ba6Ssthen 535fdfb4ba6Ssthen /* try to scan the rdata with pretty-printing, but if that fails, then 536fdfb4ba6Ssthen * scan the rdata as an unknown RR type */ 537ebf5bb73Ssthen w += sldns_wire2str_dname_scan(d, dlen, s, slen, pkt, pktlen, comprloop); 538fdfb4ba6Ssthen w += sldns_str_print(s, slen, "\t"); 539fdfb4ba6Ssthen dname_off = rrlen-(*dlen); 540fdfb4ba6Ssthen if(*dlen == 4) { 541fdfb4ba6Ssthen /* like a question-RR */ 542fdfb4ba6Ssthen uint16_t t = sldns_read_uint16(*d); 543fdfb4ba6Ssthen uint16_t c = sldns_read_uint16((*d)+2); 544fdfb4ba6Ssthen (*d)+=4; 545fdfb4ba6Ssthen (*dlen)-=4; 546fdfb4ba6Ssthen w += sldns_wire2str_class_print(s, slen, c); 547fdfb4ba6Ssthen w += sldns_str_print(s, slen, "\t"); 548fdfb4ba6Ssthen w += sldns_wire2str_type_print(s, slen, t); 549fdfb4ba6Ssthen w += sldns_str_print(s, slen, " ; Error no ttl,rdata\n"); 550fdfb4ba6Ssthen return w; 551fdfb4ba6Ssthen } 552fdfb4ba6Ssthen if(*dlen < 8) { 553fdfb4ba6Ssthen if(*dlen == 0) 554fdfb4ba6Ssthen return w + sldns_str_print(s, slen, ";Error missing RR\n"); 555fdfb4ba6Ssthen w += print_remainder_hex(";Error partial RR 0x", d, dlen, s, slen); 556fdfb4ba6Ssthen return w + sldns_str_print(s, slen, "\n"); 557fdfb4ba6Ssthen } 558fdfb4ba6Ssthen rrtype = sldns_read_uint16(*d); 559fdfb4ba6Ssthen w += sldns_rr_tcttl_scan(d, dlen, s, slen); 560fdfb4ba6Ssthen w += sldns_str_print(s, slen, "\t"); 561fdfb4ba6Ssthen 562fdfb4ba6Ssthen /* rdata */ 563fdfb4ba6Ssthen if(*dlen < 2) { 564fdfb4ba6Ssthen if(*dlen == 0) 565fdfb4ba6Ssthen return w + sldns_str_print(s, slen, ";Error missing rdatalen\n"); 566fdfb4ba6Ssthen w += print_remainder_hex(";Error missing rdatalen 0x", 567fdfb4ba6Ssthen d, dlen, s, slen); 568fdfb4ba6Ssthen return w + sldns_str_print(s, slen, "\n"); 569fdfb4ba6Ssthen } 570fdfb4ba6Ssthen rdlen = sldns_read_uint16(*d); 571fdfb4ba6Ssthen ordlen = rdlen; 572fdfb4ba6Ssthen (*d)+=2; 573fdfb4ba6Ssthen (*dlen)-=2; 574fdfb4ba6Ssthen if(*dlen < rdlen) { 575fdfb4ba6Ssthen w += sldns_str_print(s, slen, "\\# %u ", (unsigned)rdlen); 576fdfb4ba6Ssthen if(*dlen == 0) 577fdfb4ba6Ssthen return w + sldns_str_print(s, slen, ";Error missing rdata\n"); 578fdfb4ba6Ssthen w += print_remainder_hex(";Error partial rdata 0x", d, dlen, s, slen); 579fdfb4ba6Ssthen return w + sldns_str_print(s, slen, "\n"); 580fdfb4ba6Ssthen } 581ebf5bb73Ssthen w += sldns_wire2str_rdata_scan(d, &rdlen, s, slen, rrtype, pkt, pktlen, 582ebf5bb73Ssthen comprloop); 583fdfb4ba6Ssthen (*dlen) -= (ordlen-rdlen); 584fdfb4ba6Ssthen 585fdfb4ba6Ssthen /* default comment */ 586fdfb4ba6Ssthen w += sldns_wire2str_rr_comment_print(s, slen, rr, rrlen, dname_off, 587fdfb4ba6Ssthen rrtype); 588fdfb4ba6Ssthen w += sldns_str_print(s, slen, "\n"); 589fdfb4ba6Ssthen return w; 590fdfb4ba6Ssthen } 591fdfb4ba6Ssthen 592fdfb4ba6Ssthen int sldns_wire2str_rrquestion_scan(uint8_t** d, size_t* dlen, char** s, 593ebf5bb73Ssthen size_t* slen, uint8_t* pkt, size_t pktlen, int* comprloop) 594fdfb4ba6Ssthen { 595fdfb4ba6Ssthen int w = 0; 596fdfb4ba6Ssthen uint16_t t, c; 597ebf5bb73Ssthen w += sldns_wire2str_dname_scan(d, dlen, s, slen, pkt, pktlen, comprloop); 598fdfb4ba6Ssthen w += sldns_str_print(s, slen, "\t"); 599fdfb4ba6Ssthen if(*dlen < 4) { 600fdfb4ba6Ssthen if(*dlen == 0) 601fdfb4ba6Ssthen return w + sldns_str_print(s, slen, "Error malformed\n"); 602fdfb4ba6Ssthen w += print_remainder_hex("Error malformed 0x", d, dlen, s, slen); 603fdfb4ba6Ssthen return w + sldns_str_print(s, slen, "\n"); 604fdfb4ba6Ssthen } 605fdfb4ba6Ssthen t = sldns_read_uint16(*d); 606fdfb4ba6Ssthen c = sldns_read_uint16((*d)+2); 607fdfb4ba6Ssthen (*d)+=4; 608fdfb4ba6Ssthen (*dlen)-=4; 609fdfb4ba6Ssthen w += sldns_wire2str_class_print(s, slen, c); 610fdfb4ba6Ssthen w += sldns_str_print(s, slen, "\t"); 611fdfb4ba6Ssthen w += sldns_wire2str_type_print(s, slen, t); 612fdfb4ba6Ssthen w += sldns_str_print(s, slen, "\n"); 613fdfb4ba6Ssthen return w; 614fdfb4ba6Ssthen } 615fdfb4ba6Ssthen 616fdfb4ba6Ssthen int sldns_wire2str_rr_unknown_scan(uint8_t** d, size_t* dlen, char** s, 617ebf5bb73Ssthen size_t* slen, uint8_t* pkt, size_t pktlen, int* comprloop) 618fdfb4ba6Ssthen { 619fdfb4ba6Ssthen size_t rdlen, ordlen; 620fdfb4ba6Ssthen int w = 0; 621ebf5bb73Ssthen w += sldns_wire2str_dname_scan(d, dlen, s, slen, pkt, pktlen, comprloop); 622fdfb4ba6Ssthen w += sldns_str_print(s, slen, "\t"); 623fdfb4ba6Ssthen w += sldns_rr_tcttl_scan(d, dlen, s, slen); 624fdfb4ba6Ssthen w += sldns_str_print(s, slen, "\t"); 625fdfb4ba6Ssthen if(*dlen < 2) { 626fdfb4ba6Ssthen if(*dlen == 0) 627fdfb4ba6Ssthen return w + sldns_str_print(s, slen, ";Error missing rdatalen\n"); 628fdfb4ba6Ssthen w += print_remainder_hex(";Error missing rdatalen 0x", 629fdfb4ba6Ssthen d, dlen, s, slen); 630fdfb4ba6Ssthen return w + sldns_str_print(s, slen, "\n"); 631fdfb4ba6Ssthen } 632fdfb4ba6Ssthen rdlen = sldns_read_uint16(*d); 633fdfb4ba6Ssthen ordlen = rdlen; 634fdfb4ba6Ssthen (*d) += 2; 635fdfb4ba6Ssthen (*dlen) -= 2; 636fdfb4ba6Ssthen if(*dlen < rdlen) { 637fdfb4ba6Ssthen w += sldns_str_print(s, slen, "\\# %u ", (unsigned)rdlen); 638fdfb4ba6Ssthen if(*dlen == 0) 639fdfb4ba6Ssthen return w + sldns_str_print(s, slen, ";Error missing rdata\n"); 640fdfb4ba6Ssthen w += print_remainder_hex(";Error partial rdata 0x", d, dlen, s, slen); 641fdfb4ba6Ssthen return w + sldns_str_print(s, slen, "\n"); 642fdfb4ba6Ssthen } 643fdfb4ba6Ssthen w += sldns_wire2str_rdata_unknown_scan(d, &rdlen, s, slen); 644fdfb4ba6Ssthen (*dlen) -= (ordlen-rdlen); 645fdfb4ba6Ssthen w += sldns_str_print(s, slen, "\n"); 646fdfb4ba6Ssthen return w; 647fdfb4ba6Ssthen } 648fdfb4ba6Ssthen 649fdfb4ba6Ssthen /** print rr comment for type DNSKEY */ 650fdfb4ba6Ssthen static int rr_comment_dnskey(char** s, size_t* slen, uint8_t* rr, 651fdfb4ba6Ssthen size_t rrlen, size_t dname_off) 652fdfb4ba6Ssthen { 653fdfb4ba6Ssthen size_t rdlen; 654fdfb4ba6Ssthen uint8_t* rdata; 655fdfb4ba6Ssthen int flags, w = 0; 656fdfb4ba6Ssthen if(rrlen < dname_off + 10) return 0; 657fdfb4ba6Ssthen rdlen = sldns_read_uint16(rr+dname_off+8); 658fdfb4ba6Ssthen if(rrlen < dname_off + 10 + rdlen) return 0; 659ebf5bb73Ssthen if(rdlen < 2) return 0; 660fdfb4ba6Ssthen rdata = rr + dname_off + 10; 661fdfb4ba6Ssthen flags = (int)sldns_read_uint16(rdata); 662fdfb4ba6Ssthen w += sldns_str_print(s, slen, " ;{"); 663fdfb4ba6Ssthen 664fdfb4ba6Ssthen /* id */ 665fdfb4ba6Ssthen w += sldns_str_print(s, slen, "id = %u", 666fdfb4ba6Ssthen sldns_calc_keytag_raw(rdata, rdlen)); 667fdfb4ba6Ssthen 668fdfb4ba6Ssthen /* flags */ 669fdfb4ba6Ssthen if((flags&LDNS_KEY_ZONE_KEY)) { 670fdfb4ba6Ssthen if((flags&LDNS_KEY_SEP_KEY)) 671fdfb4ba6Ssthen w += sldns_str_print(s, slen, " (ksk)"); 672fdfb4ba6Ssthen else w += sldns_str_print(s, slen, " (zsk)"); 673fdfb4ba6Ssthen } 674fdfb4ba6Ssthen 675fdfb4ba6Ssthen /* keysize */ 676fdfb4ba6Ssthen if(rdlen > 4) { 677fdfb4ba6Ssthen w += sldns_str_print(s, slen, ", "); 678fdfb4ba6Ssthen w += sldns_str_print(s, slen, "size = %db", 679fdfb4ba6Ssthen (int)sldns_rr_dnskey_key_size_raw( 680fdfb4ba6Ssthen (unsigned char*)rdata+4, rdlen-4, (int)(rdata[3]))); 681fdfb4ba6Ssthen } 682fdfb4ba6Ssthen 683fdfb4ba6Ssthen w += sldns_str_print(s, slen, "}"); 684fdfb4ba6Ssthen return w; 685fdfb4ba6Ssthen } 686fdfb4ba6Ssthen 687fdfb4ba6Ssthen /** print rr comment for type RRSIG */ 688fdfb4ba6Ssthen static int rr_comment_rrsig(char** s, size_t* slen, uint8_t* rr, 689fdfb4ba6Ssthen size_t rrlen, size_t dname_off) 690fdfb4ba6Ssthen { 691fdfb4ba6Ssthen size_t rdlen; 692fdfb4ba6Ssthen uint8_t* rdata; 693fdfb4ba6Ssthen if(rrlen < dname_off + 10) return 0; 694fdfb4ba6Ssthen rdlen = sldns_read_uint16(rr+dname_off+8); 695fdfb4ba6Ssthen if(rrlen < dname_off + 10 + rdlen) return 0; 696fdfb4ba6Ssthen rdata = rr + dname_off + 10; 697fdfb4ba6Ssthen if(rdlen < 18) return 0; 698fdfb4ba6Ssthen return sldns_str_print(s, slen, " ;{id = %d}", 699fdfb4ba6Ssthen (int)sldns_read_uint16(rdata+16)); 700fdfb4ba6Ssthen } 701fdfb4ba6Ssthen 702fdfb4ba6Ssthen /** print rr comment for type NSEC3 */ 703fdfb4ba6Ssthen static int rr_comment_nsec3(char** s, size_t* slen, uint8_t* rr, 704fdfb4ba6Ssthen size_t rrlen, size_t dname_off) 705fdfb4ba6Ssthen { 706fdfb4ba6Ssthen size_t rdlen; 707fdfb4ba6Ssthen uint8_t* rdata; 708fdfb4ba6Ssthen int w = 0; 709fdfb4ba6Ssthen if(rrlen < dname_off + 10) return 0; 710fdfb4ba6Ssthen rdlen = sldns_read_uint16(rr+dname_off+8); 711fdfb4ba6Ssthen if(rrlen < dname_off + 10 + rdlen) return 0; 712fdfb4ba6Ssthen rdata = rr + dname_off + 10; 713fdfb4ba6Ssthen if(rdlen < 2) return 0; 714fdfb4ba6Ssthen if((rdata[1] & LDNS_NSEC3_VARS_OPTOUT_MASK)) 715fdfb4ba6Ssthen w += sldns_str_print(s, slen, " ;{flags: optout}"); 716fdfb4ba6Ssthen return w; 717fdfb4ba6Ssthen } 718fdfb4ba6Ssthen 719fdfb4ba6Ssthen int sldns_wire2str_rr_comment_print(char** s, size_t* slen, uint8_t* rr, 720fdfb4ba6Ssthen size_t rrlen, size_t dname_off, uint16_t rrtype) 721fdfb4ba6Ssthen { 722fdfb4ba6Ssthen if(rrtype == LDNS_RR_TYPE_DNSKEY) { 723fdfb4ba6Ssthen return rr_comment_dnskey(s, slen, rr, rrlen, dname_off); 724fdfb4ba6Ssthen } else if(rrtype == LDNS_RR_TYPE_RRSIG) { 725fdfb4ba6Ssthen return rr_comment_rrsig(s, slen, rr, rrlen, dname_off); 726fdfb4ba6Ssthen } else if(rrtype == LDNS_RR_TYPE_NSEC3) { 727fdfb4ba6Ssthen return rr_comment_nsec3(s, slen, rr, rrlen, dname_off); 728fdfb4ba6Ssthen } 729fdfb4ba6Ssthen return 0; 730fdfb4ba6Ssthen } 731fdfb4ba6Ssthen 732fdfb4ba6Ssthen int sldns_wire2str_header_scan(uint8_t** d, size_t* dlen, char** s, 733fdfb4ba6Ssthen size_t* slen) 734fdfb4ba6Ssthen { 735fdfb4ba6Ssthen int w = 0; 736fdfb4ba6Ssthen int opcode, rcode; 737fdfb4ba6Ssthen w += sldns_str_print(s, slen, ";; ->>HEADER<<- "); 738fdfb4ba6Ssthen if(*dlen == 0) 739fdfb4ba6Ssthen return w+sldns_str_print(s, slen, "Error empty packet"); 740fdfb4ba6Ssthen if(*dlen < 4) 741fdfb4ba6Ssthen return w+print_remainder_hex("Error header too short 0x", d, dlen, s, slen); 742fdfb4ba6Ssthen opcode = (int)LDNS_OPCODE_WIRE(*d); 743fdfb4ba6Ssthen rcode = (int)LDNS_RCODE_WIRE(*d); 744fdfb4ba6Ssthen w += sldns_str_print(s, slen, "opcode: "); 745fdfb4ba6Ssthen w += sldns_wire2str_opcode_print(s, slen, opcode); 746fdfb4ba6Ssthen w += sldns_str_print(s, slen, ", "); 747fdfb4ba6Ssthen w += sldns_str_print(s, slen, "rcode: "); 748fdfb4ba6Ssthen w += sldns_wire2str_rcode_print(s, slen, rcode); 749fdfb4ba6Ssthen w += sldns_str_print(s, slen, ", "); 750fdfb4ba6Ssthen w += sldns_str_print(s, slen, "id: %d\n", (int)LDNS_ID_WIRE(*d)); 751fdfb4ba6Ssthen w += sldns_str_print(s, slen, ";; flags:"); 752fdfb4ba6Ssthen if(LDNS_QR_WIRE(*d)) w += sldns_str_print(s, slen, " qr"); 753fdfb4ba6Ssthen if(LDNS_AA_WIRE(*d)) w += sldns_str_print(s, slen, " aa"); 754fdfb4ba6Ssthen if(LDNS_TC_WIRE(*d)) w += sldns_str_print(s, slen, " tc"); 755fdfb4ba6Ssthen if(LDNS_RD_WIRE(*d)) w += sldns_str_print(s, slen, " rd"); 756fdfb4ba6Ssthen if(LDNS_CD_WIRE(*d)) w += sldns_str_print(s, slen, " cd"); 757fdfb4ba6Ssthen if(LDNS_RA_WIRE(*d)) w += sldns_str_print(s, slen, " ra"); 758fdfb4ba6Ssthen if(LDNS_AD_WIRE(*d)) w += sldns_str_print(s, slen, " ad"); 759fdfb4ba6Ssthen if(LDNS_Z_WIRE(*d)) w += sldns_str_print(s, slen, " z"); 760fdfb4ba6Ssthen w += sldns_str_print(s, slen, " ; "); 761fdfb4ba6Ssthen if(*dlen < LDNS_HEADER_SIZE) 762fdfb4ba6Ssthen return w+print_remainder_hex("Error header too short 0x", d, dlen, s, slen); 763fdfb4ba6Ssthen w += sldns_str_print(s, slen, "QUERY: %d, ", (int)LDNS_QDCOUNT(*d)); 764fdfb4ba6Ssthen w += sldns_str_print(s, slen, "ANSWER: %d, ", (int)LDNS_ANCOUNT(*d)); 765fdfb4ba6Ssthen w += sldns_str_print(s, slen, "AUTHORITY: %d, ", (int)LDNS_NSCOUNT(*d)); 766fdfb4ba6Ssthen w += sldns_str_print(s, slen, "ADDITIONAL: %d ", (int)LDNS_ARCOUNT(*d)); 767fdfb4ba6Ssthen *d += LDNS_HEADER_SIZE; 768fdfb4ba6Ssthen *dlen -= LDNS_HEADER_SIZE; 769fdfb4ba6Ssthen return w; 770fdfb4ba6Ssthen } 771fdfb4ba6Ssthen 772fdfb4ba6Ssthen int sldns_wire2str_rdata_scan(uint8_t** d, size_t* dlen, char** s, 773ebf5bb73Ssthen size_t* slen, uint16_t rrtype, uint8_t* pkt, size_t pktlen, 774ebf5bb73Ssthen int* comprloop) 775fdfb4ba6Ssthen { 776fdfb4ba6Ssthen /* try to prettyprint, but if that fails, use unknown format */ 777fdfb4ba6Ssthen uint8_t* origd = *d; 778fdfb4ba6Ssthen char* origs = *s; 779fdfb4ba6Ssthen size_t origdlen = *dlen, origslen = *slen; 78077079be7Ssthen size_t r_cnt, r_max; 781fdfb4ba6Ssthen sldns_rdf_type rdftype; 782fdfb4ba6Ssthen int w = 0, n; 783fdfb4ba6Ssthen 784fdfb4ba6Ssthen const sldns_rr_descriptor *desc = sldns_rr_descript(rrtype); 785fdfb4ba6Ssthen if(!desc) /* unknown format */ 786fdfb4ba6Ssthen return sldns_wire2str_rdata_unknown_scan(d, dlen, s, slen); 787fdfb4ba6Ssthen /* dlen equals the rdatalen for the rdata */ 788fdfb4ba6Ssthen 789fdfb4ba6Ssthen r_max = sldns_rr_descriptor_maximum(desc); 790fdfb4ba6Ssthen for(r_cnt=0; r_cnt < r_max; r_cnt++) { 791fdfb4ba6Ssthen if(*dlen == 0) { 792fdfb4ba6Ssthen if(r_cnt < sldns_rr_descriptor_minimum(desc)) 793fdfb4ba6Ssthen goto failed; 794fdfb4ba6Ssthen break; /* nothing more to print */ 795fdfb4ba6Ssthen } 796fdfb4ba6Ssthen rdftype = sldns_rr_descriptor_field_type(desc, r_cnt); 797fdfb4ba6Ssthen if(r_cnt != 0) 798fdfb4ba6Ssthen w += sldns_str_print(s, slen, " "); 799fdfb4ba6Ssthen n = sldns_wire2str_rdf_scan(d, dlen, s, slen, rdftype, 800ebf5bb73Ssthen pkt, pktlen, comprloop); 801fdfb4ba6Ssthen if(n == -1) { 802fdfb4ba6Ssthen failed: 803fdfb4ba6Ssthen /* failed, use unknown format */ 804fdfb4ba6Ssthen *d = origd; *s = origs; 805fdfb4ba6Ssthen *dlen = origdlen; *slen = origslen; 806fdfb4ba6Ssthen return sldns_wire2str_rdata_unknown_scan(d, dlen, 807fdfb4ba6Ssthen s, slen); 808fdfb4ba6Ssthen } 809fdfb4ba6Ssthen w += n; 810fdfb4ba6Ssthen } 811a961b961Ssthen if(*dlen != 0) { 812a961b961Ssthen goto failed; 813a961b961Ssthen } 814fdfb4ba6Ssthen return w; 815fdfb4ba6Ssthen } 816fdfb4ba6Ssthen 817fdfb4ba6Ssthen int sldns_wire2str_rdata_unknown_scan(uint8_t** d, size_t* dlen, char** s, 818fdfb4ba6Ssthen size_t* slen) 819fdfb4ba6Ssthen { 820fdfb4ba6Ssthen int w = 0; 821fdfb4ba6Ssthen 822fdfb4ba6Ssthen /* print length */ 823fdfb4ba6Ssthen w += sldns_str_print(s, slen, "\\# %u", (unsigned)*dlen); 824fdfb4ba6Ssthen 825fdfb4ba6Ssthen /* print rdlen in hex */ 826fdfb4ba6Ssthen if(*dlen != 0) 827fdfb4ba6Ssthen w += sldns_str_print(s, slen, " "); 828fdfb4ba6Ssthen w += print_hex_buf(s, slen, *d, *dlen); 829fdfb4ba6Ssthen (*d) += *dlen; 830fdfb4ba6Ssthen (*dlen) = 0; 831fdfb4ba6Ssthen return w; 832fdfb4ba6Ssthen } 833fdfb4ba6Ssthen 834fdfb4ba6Ssthen /** print and escape one character for a domain dname */ 835fdfb4ba6Ssthen static int dname_char_print(char** s, size_t* slen, uint8_t c) 836fdfb4ba6Ssthen { 837fdfb4ba6Ssthen if(c == '.' || c == ';' || c == '(' || c == ')' || c == '\\') 838fdfb4ba6Ssthen return sldns_str_print(s, slen, "\\%c", c); 839fdfb4ba6Ssthen else if(!(isascii((unsigned char)c) && isgraph((unsigned char)c))) 840fdfb4ba6Ssthen return sldns_str_print(s, slen, "\\%03u", (unsigned)c); 841fdfb4ba6Ssthen /* plain printout */ 842fdfb4ba6Ssthen if(*slen) { 843fdfb4ba6Ssthen **s = (char)c; 844fdfb4ba6Ssthen (*s)++; 845fdfb4ba6Ssthen (*slen)--; 846fdfb4ba6Ssthen } 847fdfb4ba6Ssthen return 1; 848fdfb4ba6Ssthen } 849fdfb4ba6Ssthen 850fdfb4ba6Ssthen int sldns_wire2str_dname_scan(uint8_t** d, size_t* dlen, char** s, size_t* slen, 851ebf5bb73Ssthen uint8_t* pkt, size_t pktlen, int* comprloop) 852fdfb4ba6Ssthen { 853fdfb4ba6Ssthen int w = 0; 854fdfb4ba6Ssthen /* spool labels onto the string, use compression if its there */ 855fdfb4ba6Ssthen uint8_t* pos = *d; 856fdfb4ba6Ssthen unsigned i, counter=0; 857ebf5bb73Ssthen unsigned maxcompr = MAX_COMPRESS_PTRS; /* loop detection, max compr ptrs */ 858fdfb4ba6Ssthen int in_buf = 1; 859e21c60efSsthen size_t dname_len = 0; 860ebf5bb73Ssthen if(comprloop) { 861ebf5bb73Ssthen if(*comprloop != 0) 862ebf5bb73Ssthen maxcompr = 30; /* for like ipv6 reverse name, per label */ 863ebf5bb73Ssthen if(*comprloop > 4) 864ebf5bb73Ssthen maxcompr = 4; /* just don't want to spend time, any more */ 865ebf5bb73Ssthen } 866fdfb4ba6Ssthen if(*dlen == 0) return sldns_str_print(s, slen, "ErrorMissingDname"); 867fdfb4ba6Ssthen if(*pos == 0) { 868fdfb4ba6Ssthen (*d)++; 869fdfb4ba6Ssthen (*dlen)--; 870fdfb4ba6Ssthen return sldns_str_print(s, slen, "."); 871fdfb4ba6Ssthen } 872ebf5bb73Ssthen while((!pkt || pos < pkt+pktlen) && *pos) { 873fdfb4ba6Ssthen /* read label length */ 874fdfb4ba6Ssthen uint8_t labellen = *pos++; 875fdfb4ba6Ssthen if(in_buf) { (*d)++; (*dlen)--; } 876fdfb4ba6Ssthen 877fdfb4ba6Ssthen /* find out what sort of label we have */ 878fdfb4ba6Ssthen if((labellen&0xc0) == 0xc0) { 879fdfb4ba6Ssthen /* compressed */ 880fdfb4ba6Ssthen uint16_t target = 0; 881fdfb4ba6Ssthen if(in_buf && *dlen == 0) 882fdfb4ba6Ssthen return w + sldns_str_print(s, slen, 883fdfb4ba6Ssthen "ErrorPartialDname"); 884fdfb4ba6Ssthen else if(!in_buf && pos+1 > pkt+pktlen) 885fdfb4ba6Ssthen return w + sldns_str_print(s, slen, 886fdfb4ba6Ssthen "ErrorPartialDname"); 887fdfb4ba6Ssthen target = ((labellen&0x3f)<<8) | *pos; 888fdfb4ba6Ssthen if(in_buf) { (*d)++; (*dlen)--; } 889fdfb4ba6Ssthen /* move to target, if possible */ 890fdfb4ba6Ssthen if(!pkt || target >= pktlen) 891fdfb4ba6Ssthen return w + sldns_str_print(s, slen, 892fdfb4ba6Ssthen "ErrorComprPtrOutOfBounds"); 893ebf5bb73Ssthen if(counter++ > maxcompr) { 894ebf5bb73Ssthen if(comprloop && *comprloop < 10) 895ebf5bb73Ssthen (*comprloop)++; 896fdfb4ba6Ssthen return w + sldns_str_print(s, slen, 897fdfb4ba6Ssthen "ErrorComprPtrLooped"); 898ebf5bb73Ssthen } 899fdfb4ba6Ssthen in_buf = 0; 900fdfb4ba6Ssthen pos = pkt+target; 901fdfb4ba6Ssthen continue; 902fdfb4ba6Ssthen } else if((labellen&0xc0)) { 903fdfb4ba6Ssthen /* notimpl label type */ 904fdfb4ba6Ssthen w += sldns_str_print(s, slen, 905fdfb4ba6Ssthen "ErrorLABELTYPE%xIsUnknown", 906fdfb4ba6Ssthen (int)(labellen&0xc0)); 907fdfb4ba6Ssthen return w; 908fdfb4ba6Ssthen } 909fdfb4ba6Ssthen 910fdfb4ba6Ssthen /* spool label characters, end with '.' */ 91177079be7Ssthen if(in_buf && *dlen < (size_t)labellen) 91277079be7Ssthen labellen = (uint8_t)*dlen; 91377079be7Ssthen else if(!in_buf && pos+(size_t)labellen > pkt+pktlen) 914fdfb4ba6Ssthen labellen = (uint8_t)(pkt + pktlen - pos); 915e21c60efSsthen dname_len += ((size_t)labellen)+1; 916e21c60efSsthen if(dname_len > LDNS_MAX_DOMAINLEN) { 917e21c60efSsthen /* dname_len counts the uncompressed length we have 918e21c60efSsthen * seen so far, and the domain name has become too 919e21c60efSsthen * long, prevent the loop from printing overly long 920e21c60efSsthen * content. */ 921e21c60efSsthen w += sldns_str_print(s, slen, 922e21c60efSsthen "ErrorDomainNameTooLong"); 923e21c60efSsthen return w; 924e21c60efSsthen } 925fdfb4ba6Ssthen for(i=0; i<(unsigned)labellen; i++) { 926fdfb4ba6Ssthen w += dname_char_print(s, slen, *pos++); 927fdfb4ba6Ssthen } 928fdfb4ba6Ssthen if(in_buf) { 929fdfb4ba6Ssthen (*d) += labellen; 930fdfb4ba6Ssthen (*dlen) -= labellen; 931fdfb4ba6Ssthen if(*dlen == 0) break; 932fdfb4ba6Ssthen } 933fdfb4ba6Ssthen w += sldns_str_print(s, slen, "."); 934fdfb4ba6Ssthen } 935fdfb4ba6Ssthen /* skip over final root label */ 936fdfb4ba6Ssthen if(in_buf && *dlen > 0) { (*d)++; (*dlen)--; } 937fdfb4ba6Ssthen /* in case we printed no labels, terminate dname */ 938fdfb4ba6Ssthen if(w == 0) w += sldns_str_print(s, slen, "."); 939fdfb4ba6Ssthen return w; 940fdfb4ba6Ssthen } 941fdfb4ba6Ssthen 942fdfb4ba6Ssthen int sldns_wire2str_opcode_print(char** s, size_t* slen, int opcode) 943fdfb4ba6Ssthen { 944fdfb4ba6Ssthen sldns_lookup_table *lt = sldns_lookup_by_id(sldns_opcodes, opcode); 945fdfb4ba6Ssthen if (lt && lt->name) { 946fdfb4ba6Ssthen return sldns_str_print(s, slen, "%s", lt->name); 947fdfb4ba6Ssthen } 948fdfb4ba6Ssthen return sldns_str_print(s, slen, "OPCODE%u", (unsigned)opcode); 949fdfb4ba6Ssthen } 950fdfb4ba6Ssthen 951fdfb4ba6Ssthen int sldns_wire2str_rcode_print(char** s, size_t* slen, int rcode) 952fdfb4ba6Ssthen { 953fdfb4ba6Ssthen sldns_lookup_table *lt = sldns_lookup_by_id(sldns_rcodes, rcode); 954fdfb4ba6Ssthen if (lt && lt->name) { 955fdfb4ba6Ssthen return sldns_str_print(s, slen, "%s", lt->name); 956fdfb4ba6Ssthen } 957fdfb4ba6Ssthen return sldns_str_print(s, slen, "RCODE%u", (unsigned)rcode); 958fdfb4ba6Ssthen } 959fdfb4ba6Ssthen 960fdfb4ba6Ssthen int sldns_wire2str_class_print(char** s, size_t* slen, uint16_t rrclass) 961fdfb4ba6Ssthen { 962fdfb4ba6Ssthen sldns_lookup_table *lt = sldns_lookup_by_id(sldns_rr_classes, 963fdfb4ba6Ssthen (int)rrclass); 964fdfb4ba6Ssthen if (lt && lt->name) { 965fdfb4ba6Ssthen return sldns_str_print(s, slen, "%s", lt->name); 966fdfb4ba6Ssthen } 967fdfb4ba6Ssthen return sldns_str_print(s, slen, "CLASS%u", (unsigned)rrclass); 968fdfb4ba6Ssthen } 969fdfb4ba6Ssthen 970fdfb4ba6Ssthen int sldns_wire2str_type_print(char** s, size_t* slen, uint16_t rrtype) 971fdfb4ba6Ssthen { 972fdfb4ba6Ssthen const sldns_rr_descriptor *descriptor = sldns_rr_descript(rrtype); 973fdfb4ba6Ssthen if (descriptor && descriptor->_name) { 974fdfb4ba6Ssthen return sldns_str_print(s, slen, "%s", descriptor->_name); 975fdfb4ba6Ssthen } 976fdfb4ba6Ssthen return sldns_str_print(s, slen, "TYPE%u", (unsigned)rrtype); 977fdfb4ba6Ssthen } 978fdfb4ba6Ssthen 979fdfb4ba6Ssthen int sldns_wire2str_edns_option_code_print(char** s, size_t* slen, 980fdfb4ba6Ssthen uint16_t opcode) 981fdfb4ba6Ssthen { 982fdfb4ba6Ssthen sldns_lookup_table *lt = sldns_lookup_by_id(sldns_edns_options, 983fdfb4ba6Ssthen (int)opcode); 984fdfb4ba6Ssthen if (lt && lt->name) { 985fdfb4ba6Ssthen return sldns_str_print(s, slen, "%s", lt->name); 986fdfb4ba6Ssthen } 987fdfb4ba6Ssthen return sldns_str_print(s, slen, "OPT%u", (unsigned)opcode); 988fdfb4ba6Ssthen } 989fdfb4ba6Ssthen 990fdfb4ba6Ssthen int sldns_wire2str_class_scan(uint8_t** d, size_t* dlen, char** s, size_t* slen) 991fdfb4ba6Ssthen { 992fdfb4ba6Ssthen uint16_t c; 993fdfb4ba6Ssthen if(*dlen == 0) return 0; 994fdfb4ba6Ssthen if(*dlen < 2) return print_remainder_hex("Error malformed 0x", d, dlen, s, slen); 995fdfb4ba6Ssthen c = sldns_read_uint16(*d); 996fdfb4ba6Ssthen (*d)+=2; 997fdfb4ba6Ssthen (*dlen)-=2; 998fdfb4ba6Ssthen return sldns_wire2str_class_print(s, slen, c); 999fdfb4ba6Ssthen } 1000fdfb4ba6Ssthen 1001fdfb4ba6Ssthen int sldns_wire2str_type_scan(uint8_t** d, size_t* dlen, char** s, size_t* slen) 1002fdfb4ba6Ssthen { 1003fdfb4ba6Ssthen uint16_t t; 1004fdfb4ba6Ssthen if(*dlen == 0) return 0; 1005fdfb4ba6Ssthen if(*dlen < 2) return print_remainder_hex("Error malformed 0x", d, dlen, s, slen); 1006fdfb4ba6Ssthen t = sldns_read_uint16(*d); 1007fdfb4ba6Ssthen (*d)+=2; 1008fdfb4ba6Ssthen (*dlen)-=2; 1009fdfb4ba6Ssthen return sldns_wire2str_type_print(s, slen, t); 1010fdfb4ba6Ssthen } 1011fdfb4ba6Ssthen 1012fdfb4ba6Ssthen int sldns_wire2str_ttl_scan(uint8_t** d, size_t* dlen, char** s, size_t* slen) 1013fdfb4ba6Ssthen { 1014fdfb4ba6Ssthen uint32_t ttl; 1015fdfb4ba6Ssthen if(*dlen == 0) return 0; 1016fdfb4ba6Ssthen if(*dlen < 4) return print_remainder_hex("Error malformed 0x", d, dlen, s, slen); 1017fdfb4ba6Ssthen ttl = sldns_read_uint32(*d); 1018fdfb4ba6Ssthen (*d)+=4; 1019fdfb4ba6Ssthen (*dlen)-=4; 1020fdfb4ba6Ssthen return sldns_str_print(s, slen, "%u", (unsigned)ttl); 1021fdfb4ba6Ssthen } 1022fdfb4ba6Ssthen 1023191f22c6Ssthen static int 1024191f22c6Ssthen sldns_print_svcparamkey(char** s, size_t* slen, uint16_t svcparamkey) 1025191f22c6Ssthen { 1026191f22c6Ssthen if (svcparamkey < SVCPARAMKEY_COUNT) { 1027191f22c6Ssthen return sldns_str_print(s, slen, "%s", svcparamkey_strs[svcparamkey]); 1028191f22c6Ssthen } 1029191f22c6Ssthen else { 1030191f22c6Ssthen return sldns_str_print(s, slen, "key%d", (int)svcparamkey); 1031191f22c6Ssthen } 1032191f22c6Ssthen } 1033191f22c6Ssthen 1034191f22c6Ssthen static int sldns_wire2str_svcparam_port2str(char** s, 1035191f22c6Ssthen size_t* slen, uint16_t data_len, uint8_t* data) 1036191f22c6Ssthen { 1037191f22c6Ssthen int w = 0; 1038191f22c6Ssthen 1039191f22c6Ssthen if (data_len != 2) 1040191f22c6Ssthen return -1; /* wireformat error, a short is 2 bytes */ 1041191f22c6Ssthen w = sldns_str_print(s, slen, "=%d", (int)sldns_read_uint16(data)); 1042191f22c6Ssthen 1043191f22c6Ssthen return w; 1044191f22c6Ssthen } 1045191f22c6Ssthen 1046191f22c6Ssthen static int sldns_wire2str_svcparam_ipv4hint2str(char** s, 1047191f22c6Ssthen size_t* slen, uint16_t data_len, uint8_t* data) 1048191f22c6Ssthen { 1049191f22c6Ssthen char ip_str[INET_ADDRSTRLEN + 1]; 1050191f22c6Ssthen 1051191f22c6Ssthen int w = 0; 1052191f22c6Ssthen 1053191f22c6Ssthen assert(data_len > 0); 1054191f22c6Ssthen 1055191f22c6Ssthen if ((data_len % LDNS_IP4ADDRLEN) == 0) { 1056191f22c6Ssthen if (inet_ntop(AF_INET, data, ip_str, sizeof(ip_str)) == NULL) 1057191f22c6Ssthen return -1; /* wireformat error, incorrect size or inet family */ 1058191f22c6Ssthen 1059191f22c6Ssthen w += sldns_str_print(s, slen, "=%s", ip_str); 1060191f22c6Ssthen data += LDNS_IP4ADDRLEN; 1061191f22c6Ssthen 1062191f22c6Ssthen while ((data_len -= LDNS_IP4ADDRLEN) > 0) { 1063191f22c6Ssthen if (inet_ntop(AF_INET, data, ip_str, sizeof(ip_str)) == NULL) 1064191f22c6Ssthen return -1; /* wireformat error, incorrect size or inet family */ 1065191f22c6Ssthen 1066191f22c6Ssthen w += sldns_str_print(s, slen, ",%s", ip_str); 1067191f22c6Ssthen data += LDNS_IP4ADDRLEN; 1068191f22c6Ssthen } 1069191f22c6Ssthen } else 1070191f22c6Ssthen return -1; 1071191f22c6Ssthen 1072191f22c6Ssthen return w; 1073191f22c6Ssthen } 1074191f22c6Ssthen 1075191f22c6Ssthen static int sldns_wire2str_svcparam_ipv6hint2str(char** s, 1076191f22c6Ssthen size_t* slen, uint16_t data_len, uint8_t* data) 1077191f22c6Ssthen { 1078191f22c6Ssthen char ip_str[INET6_ADDRSTRLEN + 1]; 1079191f22c6Ssthen 1080191f22c6Ssthen int w = 0; 1081191f22c6Ssthen 1082191f22c6Ssthen assert(data_len > 0); 1083191f22c6Ssthen 1084191f22c6Ssthen if ((data_len % LDNS_IP6ADDRLEN) == 0) { 1085191f22c6Ssthen if (inet_ntop(AF_INET6, data, ip_str, sizeof(ip_str)) == NULL) 1086191f22c6Ssthen return -1; /* wireformat error, incorrect size or inet family */ 1087191f22c6Ssthen 1088191f22c6Ssthen w += sldns_str_print(s, slen, "=%s", ip_str); 1089191f22c6Ssthen data += LDNS_IP6ADDRLEN; 1090191f22c6Ssthen 1091191f22c6Ssthen while ((data_len -= LDNS_IP6ADDRLEN) > 0) { 1092191f22c6Ssthen if (inet_ntop(AF_INET6, data, ip_str, sizeof(ip_str)) == NULL) 1093191f22c6Ssthen return -1; /* wireformat error, incorrect size or inet family */ 1094191f22c6Ssthen 1095191f22c6Ssthen w += sldns_str_print(s, slen, ",%s", ip_str); 1096191f22c6Ssthen data += LDNS_IP6ADDRLEN; 1097191f22c6Ssthen } 1098191f22c6Ssthen } else 1099191f22c6Ssthen return -1; 1100191f22c6Ssthen 1101191f22c6Ssthen return w; 1102191f22c6Ssthen } 1103191f22c6Ssthen 1104191f22c6Ssthen static int sldns_wire2str_svcparam_mandatory2str(char** s, 1105191f22c6Ssthen size_t* slen, uint16_t data_len, uint8_t* data) 1106191f22c6Ssthen { 1107191f22c6Ssthen int w = 0; 1108191f22c6Ssthen 1109191f22c6Ssthen assert(data_len > 0); 1110191f22c6Ssthen 1111191f22c6Ssthen if (data_len % sizeof(uint16_t)) 1112d1e2768aSsthen return -1; /* wireformat error, data_len must be multiple of shorts */ 1113191f22c6Ssthen w += sldns_str_print(s, slen, "="); 1114191f22c6Ssthen w += sldns_print_svcparamkey(s, slen, sldns_read_uint16(data)); 1115191f22c6Ssthen data += 2; 1116191f22c6Ssthen 1117191f22c6Ssthen while ((data_len -= sizeof(uint16_t))) { 1118191f22c6Ssthen w += sldns_str_print(s, slen, ","); 1119191f22c6Ssthen w += sldns_print_svcparamkey(s, slen, sldns_read_uint16(data)); 1120191f22c6Ssthen data += 2; 1121191f22c6Ssthen } 1122191f22c6Ssthen 1123191f22c6Ssthen return w; 1124191f22c6Ssthen } 1125191f22c6Ssthen 1126191f22c6Ssthen static int sldns_wire2str_svcparam_alpn2str(char** s, 1127191f22c6Ssthen size_t* slen, uint16_t data_len, uint8_t* data) 1128191f22c6Ssthen { 1129191f22c6Ssthen uint8_t *dp = (void *)data; 1130191f22c6Ssthen int w = 0; 1131191f22c6Ssthen 1132191f22c6Ssthen assert(data_len > 0); /* Guaranteed by sldns_wire2str_svcparam_scan */ 1133191f22c6Ssthen 1134191f22c6Ssthen w += sldns_str_print(s, slen, "=\""); 1135191f22c6Ssthen while (data_len) { 1136191f22c6Ssthen /* alpn is list of length byte (str_len) followed by a string of that size */ 1137191f22c6Ssthen uint8_t i, str_len = *dp++; 1138191f22c6Ssthen 1139191f22c6Ssthen if (str_len > --data_len) 1140191f22c6Ssthen return -1; 1141191f22c6Ssthen 1142191f22c6Ssthen for (i = 0; i < str_len; i++) { 1143191f22c6Ssthen if (dp[i] == '"' || dp[i] == '\\') 1144191f22c6Ssthen w += sldns_str_print(s, slen, "\\\\\\%c", dp[i]); 1145191f22c6Ssthen 1146191f22c6Ssthen else if (dp[i] == ',') 1147191f22c6Ssthen w += sldns_str_print(s, slen, "\\\\%c", dp[i]); 1148191f22c6Ssthen 1149191f22c6Ssthen else if (!isprint(dp[i])) 1150191f22c6Ssthen w += sldns_str_print(s, slen, "\\%03u", (unsigned) dp[i]); 1151191f22c6Ssthen 1152191f22c6Ssthen else 1153191f22c6Ssthen w += sldns_str_print(s, slen, "%c", dp[i]); 1154191f22c6Ssthen } 1155191f22c6Ssthen dp += str_len; 1156191f22c6Ssthen if ((data_len -= str_len)) 1157191f22c6Ssthen w += sldns_str_print(s, slen, "%s", ","); 1158191f22c6Ssthen } 1159191f22c6Ssthen w += sldns_str_print(s, slen, "\""); 1160191f22c6Ssthen 1161191f22c6Ssthen return w; 1162191f22c6Ssthen } 1163191f22c6Ssthen 1164191f22c6Ssthen static int sldns_wire2str_svcparam_ech2str(char** s, 1165191f22c6Ssthen size_t* slen, uint16_t data_len, uint8_t* data) 1166191f22c6Ssthen { 1167191f22c6Ssthen int size; 1168191f22c6Ssthen int w = 0; 1169191f22c6Ssthen 1170191f22c6Ssthen assert(data_len > 0); /* Guaranteed by sldns_wire2str_svcparam_scan */ 1171191f22c6Ssthen 1172191f22c6Ssthen w += sldns_str_print(s, slen, "=\""); 1173191f22c6Ssthen 1174191f22c6Ssthen if ((size = sldns_b64_ntop(data, data_len, *s, *slen)) < 0) 1175191f22c6Ssthen return -1; 1176191f22c6Ssthen 1177191f22c6Ssthen (*s) += size; 1178191f22c6Ssthen (*slen) -= size; 1179191f22c6Ssthen 1180191f22c6Ssthen w += sldns_str_print(s, slen, "\""); 1181191f22c6Ssthen 1182191f22c6Ssthen return w + size; 1183191f22c6Ssthen } 1184191f22c6Ssthen 1185191f22c6Ssthen int sldns_wire2str_svcparam_scan(uint8_t** d, size_t* dlen, char** s, size_t* slen) 1186191f22c6Ssthen { 1187191f22c6Ssthen uint8_t ch; 1188191f22c6Ssthen uint16_t svcparamkey, data_len; 1189191f22c6Ssthen int written_chars = 0; 1190191f22c6Ssthen int r, i; 1191191f22c6Ssthen 1192191f22c6Ssthen /* verify that we have enough data to read svcparamkey and data_len */ 1193191f22c6Ssthen if(*dlen < 4) 1194191f22c6Ssthen return -1; 1195191f22c6Ssthen 1196191f22c6Ssthen svcparamkey = sldns_read_uint16(*d); 1197191f22c6Ssthen data_len = sldns_read_uint16(*d+2); 1198191f22c6Ssthen *d += 4; 1199191f22c6Ssthen *dlen -= 4; 1200191f22c6Ssthen 1201191f22c6Ssthen /* verify that we have data_len data */ 1202191f22c6Ssthen if (data_len > *dlen) 1203191f22c6Ssthen return -1; 1204191f22c6Ssthen 1205191f22c6Ssthen written_chars += sldns_print_svcparamkey(s, slen, svcparamkey); 1206191f22c6Ssthen if (!data_len) { 1207191f22c6Ssthen 1208191f22c6Ssthen /* Some SvcParams MUST have values */ 1209191f22c6Ssthen switch (svcparamkey) { 1210191f22c6Ssthen case SVCB_KEY_ALPN: 1211191f22c6Ssthen case SVCB_KEY_PORT: 1212191f22c6Ssthen case SVCB_KEY_IPV4HINT: 1213191f22c6Ssthen case SVCB_KEY_IPV6HINT: 1214191f22c6Ssthen case SVCB_KEY_MANDATORY: 12158b7325afSsthen case SVCB_KEY_DOHPATH: 1216191f22c6Ssthen return -1; 1217191f22c6Ssthen default: 1218191f22c6Ssthen return written_chars; 1219191f22c6Ssthen } 1220191f22c6Ssthen } 1221191f22c6Ssthen 1222191f22c6Ssthen switch (svcparamkey) { 1223191f22c6Ssthen case SVCB_KEY_PORT: 1224191f22c6Ssthen r = sldns_wire2str_svcparam_port2str(s, slen, data_len, *d); 1225191f22c6Ssthen break; 1226191f22c6Ssthen case SVCB_KEY_IPV4HINT: 1227191f22c6Ssthen r = sldns_wire2str_svcparam_ipv4hint2str(s, slen, data_len, *d); 1228191f22c6Ssthen break; 1229191f22c6Ssthen case SVCB_KEY_IPV6HINT: 1230191f22c6Ssthen r = sldns_wire2str_svcparam_ipv6hint2str(s, slen, data_len, *d); 1231191f22c6Ssthen break; 1232191f22c6Ssthen case SVCB_KEY_MANDATORY: 1233191f22c6Ssthen r = sldns_wire2str_svcparam_mandatory2str(s, slen, data_len, *d); 1234191f22c6Ssthen break; 1235191f22c6Ssthen case SVCB_KEY_NO_DEFAULT_ALPN: 1236191f22c6Ssthen return -1; /* wireformat error, should not have a value */ 1237191f22c6Ssthen case SVCB_KEY_ALPN: 1238191f22c6Ssthen r = sldns_wire2str_svcparam_alpn2str(s, slen, data_len, *d); 1239191f22c6Ssthen break; 1240191f22c6Ssthen case SVCB_KEY_ECH: 1241191f22c6Ssthen r = sldns_wire2str_svcparam_ech2str(s, slen, data_len, *d); 1242191f22c6Ssthen break; 12438b7325afSsthen case SVCB_KEY_DOHPATH: 1244*98bc733bSsthen ATTR_FALLTHROUGH 12458b7325afSsthen /* fallthrough */ 1246191f22c6Ssthen default: 1247191f22c6Ssthen r = sldns_str_print(s, slen, "=\""); 1248191f22c6Ssthen 1249191f22c6Ssthen for (i = 0; i < data_len; i++) { 1250191f22c6Ssthen ch = (*d)[i]; 1251191f22c6Ssthen 1252191f22c6Ssthen if (ch == '"' || ch == '\\') 1253191f22c6Ssthen r += sldns_str_print(s, slen, "\\%c", ch); 1254191f22c6Ssthen 1255191f22c6Ssthen else if (!isprint(ch)) 1256191f22c6Ssthen r += sldns_str_print(s, slen, "\\%03u", (unsigned) ch); 1257191f22c6Ssthen 1258191f22c6Ssthen else 1259191f22c6Ssthen r += sldns_str_print(s, slen, "%c", ch); 1260191f22c6Ssthen 1261191f22c6Ssthen } 1262191f22c6Ssthen r += sldns_str_print(s, slen, "\""); 1263191f22c6Ssthen break; 1264191f22c6Ssthen } 1265191f22c6Ssthen if (r <= 0) 1266191f22c6Ssthen return -1; /* wireformat error */ 1267191f22c6Ssthen 1268191f22c6Ssthen written_chars += r; 1269191f22c6Ssthen *d += data_len; 1270191f22c6Ssthen *dlen -= data_len; 1271191f22c6Ssthen return written_chars; 1272191f22c6Ssthen } 1273191f22c6Ssthen 1274fdfb4ba6Ssthen int sldns_wire2str_rdf_scan(uint8_t** d, size_t* dlen, char** s, size_t* slen, 1275ebf5bb73Ssthen int rdftype, uint8_t* pkt, size_t pktlen, int* comprloop) 1276fdfb4ba6Ssthen { 1277fdfb4ba6Ssthen if(*dlen == 0) return 0; 1278fdfb4ba6Ssthen switch(rdftype) { 1279fdfb4ba6Ssthen case LDNS_RDF_TYPE_NONE: 1280fdfb4ba6Ssthen return 0; 1281fdfb4ba6Ssthen case LDNS_RDF_TYPE_DNAME: 1282ebf5bb73Ssthen return sldns_wire2str_dname_scan(d, dlen, s, slen, pkt, pktlen, comprloop); 1283fdfb4ba6Ssthen case LDNS_RDF_TYPE_INT8: 1284fdfb4ba6Ssthen return sldns_wire2str_int8_scan(d, dlen, s, slen); 1285fdfb4ba6Ssthen case LDNS_RDF_TYPE_INT16: 1286fdfb4ba6Ssthen return sldns_wire2str_int16_scan(d, dlen, s, slen); 1287fdfb4ba6Ssthen case LDNS_RDF_TYPE_INT32: 1288fdfb4ba6Ssthen return sldns_wire2str_int32_scan(d, dlen, s, slen); 1289fdfb4ba6Ssthen case LDNS_RDF_TYPE_PERIOD: 1290fdfb4ba6Ssthen return sldns_wire2str_period_scan(d, dlen, s, slen); 1291fdfb4ba6Ssthen case LDNS_RDF_TYPE_TSIGTIME: 1292fdfb4ba6Ssthen return sldns_wire2str_tsigtime_scan(d, dlen, s, slen); 1293fdfb4ba6Ssthen case LDNS_RDF_TYPE_A: 1294fdfb4ba6Ssthen return sldns_wire2str_a_scan(d, dlen, s, slen); 1295fdfb4ba6Ssthen case LDNS_RDF_TYPE_AAAA: 1296fdfb4ba6Ssthen return sldns_wire2str_aaaa_scan(d, dlen, s, slen); 1297fdfb4ba6Ssthen case LDNS_RDF_TYPE_STR: 1298fdfb4ba6Ssthen return sldns_wire2str_str_scan(d, dlen, s, slen); 1299fdfb4ba6Ssthen case LDNS_RDF_TYPE_APL: 1300fdfb4ba6Ssthen return sldns_wire2str_apl_scan(d, dlen, s, slen); 1301fdfb4ba6Ssthen case LDNS_RDF_TYPE_B32_EXT: 1302fdfb4ba6Ssthen return sldns_wire2str_b32_ext_scan(d, dlen, s, slen); 1303fdfb4ba6Ssthen case LDNS_RDF_TYPE_B64: 1304fdfb4ba6Ssthen return sldns_wire2str_b64_scan(d, dlen, s, slen); 1305fdfb4ba6Ssthen case LDNS_RDF_TYPE_HEX: 1306fdfb4ba6Ssthen return sldns_wire2str_hex_scan(d, dlen, s, slen); 1307fdfb4ba6Ssthen case LDNS_RDF_TYPE_NSEC: 1308fdfb4ba6Ssthen return sldns_wire2str_nsec_scan(d, dlen, s, slen); 1309fdfb4ba6Ssthen case LDNS_RDF_TYPE_NSEC3_SALT: 1310fdfb4ba6Ssthen return sldns_wire2str_nsec3_salt_scan(d, dlen, s, slen); 1311fdfb4ba6Ssthen case LDNS_RDF_TYPE_TYPE: 1312fdfb4ba6Ssthen return sldns_wire2str_type_scan(d, dlen, s, slen); 1313fdfb4ba6Ssthen case LDNS_RDF_TYPE_CLASS: 1314fdfb4ba6Ssthen return sldns_wire2str_class_scan(d, dlen, s, slen); 1315fdfb4ba6Ssthen case LDNS_RDF_TYPE_CERT_ALG: 1316fdfb4ba6Ssthen return sldns_wire2str_cert_alg_scan(d, dlen, s, slen); 1317fdfb4ba6Ssthen case LDNS_RDF_TYPE_ALG: 1318fdfb4ba6Ssthen return sldns_wire2str_alg_scan(d, dlen, s, slen); 1319fdfb4ba6Ssthen case LDNS_RDF_TYPE_UNKNOWN: 1320fdfb4ba6Ssthen return sldns_wire2str_unknown_scan(d, dlen, s, slen); 1321fdfb4ba6Ssthen case LDNS_RDF_TYPE_TIME: 1322fdfb4ba6Ssthen return sldns_wire2str_time_scan(d, dlen, s, slen); 1323fdfb4ba6Ssthen case LDNS_RDF_TYPE_LOC: 1324fdfb4ba6Ssthen return sldns_wire2str_loc_scan(d, dlen, s, slen); 1325fdfb4ba6Ssthen case LDNS_RDF_TYPE_WKS: 1326fdfb4ba6Ssthen case LDNS_RDF_TYPE_SERVICE: 1327fdfb4ba6Ssthen return sldns_wire2str_wks_scan(d, dlen, s, slen); 1328fdfb4ba6Ssthen case LDNS_RDF_TYPE_NSAP: 1329fdfb4ba6Ssthen return sldns_wire2str_nsap_scan(d, dlen, s, slen); 1330fdfb4ba6Ssthen case LDNS_RDF_TYPE_ATMA: 1331fdfb4ba6Ssthen return sldns_wire2str_atma_scan(d, dlen, s, slen); 1332fdfb4ba6Ssthen case LDNS_RDF_TYPE_IPSECKEY: 1333fdfb4ba6Ssthen return sldns_wire2str_ipseckey_scan(d, dlen, s, slen, pkt, 1334ebf5bb73Ssthen pktlen, comprloop); 1335fdfb4ba6Ssthen case LDNS_RDF_TYPE_HIP: 1336fdfb4ba6Ssthen return sldns_wire2str_hip_scan(d, dlen, s, slen); 1337fdfb4ba6Ssthen case LDNS_RDF_TYPE_INT16_DATA: 1338fdfb4ba6Ssthen return sldns_wire2str_int16_data_scan(d, dlen, s, slen); 1339fdfb4ba6Ssthen case LDNS_RDF_TYPE_NSEC3_NEXT_OWNER: 1340fdfb4ba6Ssthen return sldns_wire2str_b32_ext_scan(d, dlen, s, slen); 1341fdfb4ba6Ssthen case LDNS_RDF_TYPE_ILNP64: 1342fdfb4ba6Ssthen return sldns_wire2str_ilnp64_scan(d, dlen, s, slen); 1343fdfb4ba6Ssthen case LDNS_RDF_TYPE_EUI48: 1344fdfb4ba6Ssthen return sldns_wire2str_eui48_scan(d, dlen, s, slen); 1345fdfb4ba6Ssthen case LDNS_RDF_TYPE_EUI64: 1346fdfb4ba6Ssthen return sldns_wire2str_eui64_scan(d, dlen, s, slen); 1347fdfb4ba6Ssthen case LDNS_RDF_TYPE_TAG: 1348fdfb4ba6Ssthen return sldns_wire2str_tag_scan(d, dlen, s, slen); 1349fdfb4ba6Ssthen case LDNS_RDF_TYPE_LONG_STR: 1350fdfb4ba6Ssthen return sldns_wire2str_long_str_scan(d, dlen, s, slen); 1351191f22c6Ssthen case LDNS_RDF_TYPE_SVCPARAM: 1352191f22c6Ssthen return sldns_wire2str_svcparam_scan(d, dlen, s, slen); 13532be9e038Ssthen case LDNS_RDF_TYPE_TSIGERROR: 13542be9e038Ssthen return sldns_wire2str_tsigerror_scan(d, dlen, s, slen); 1355fdfb4ba6Ssthen } 1356fdfb4ba6Ssthen /* unknown rdf type */ 1357fdfb4ba6Ssthen return -1; 1358fdfb4ba6Ssthen } 1359fdfb4ba6Ssthen 1360fdfb4ba6Ssthen int sldns_wire2str_int8_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) 1361fdfb4ba6Ssthen { 1362fdfb4ba6Ssthen int w; 1363fdfb4ba6Ssthen if(*dl < 1) return -1; 1364fdfb4ba6Ssthen w = sldns_str_print(s, sl, "%u", (unsigned)**d); 1365fdfb4ba6Ssthen (*d)++; 1366fdfb4ba6Ssthen (*dl)--; 1367fdfb4ba6Ssthen return w; 1368fdfb4ba6Ssthen } 1369fdfb4ba6Ssthen 1370fdfb4ba6Ssthen int sldns_wire2str_int16_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) 1371fdfb4ba6Ssthen { 1372fdfb4ba6Ssthen int w; 1373fdfb4ba6Ssthen if(*dl < 2) return -1; 1374fdfb4ba6Ssthen w = sldns_str_print(s, sl, "%lu", (unsigned long)sldns_read_uint16(*d)); 1375fdfb4ba6Ssthen (*d)+=2; 1376fdfb4ba6Ssthen (*dl)-=2; 1377fdfb4ba6Ssthen return w; 1378fdfb4ba6Ssthen } 1379fdfb4ba6Ssthen 1380fdfb4ba6Ssthen int sldns_wire2str_int32_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) 1381fdfb4ba6Ssthen { 1382fdfb4ba6Ssthen int w; 1383fdfb4ba6Ssthen if(*dl < 4) return -1; 1384fdfb4ba6Ssthen w = sldns_str_print(s, sl, "%lu", (unsigned long)sldns_read_uint32(*d)); 1385fdfb4ba6Ssthen (*d)+=4; 1386fdfb4ba6Ssthen (*dl)-=4; 1387fdfb4ba6Ssthen return w; 1388fdfb4ba6Ssthen } 1389fdfb4ba6Ssthen 1390fdfb4ba6Ssthen int sldns_wire2str_period_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) 1391fdfb4ba6Ssthen { 1392fdfb4ba6Ssthen int w; 1393fdfb4ba6Ssthen if(*dl < 4) return -1; 1394fdfb4ba6Ssthen w = sldns_str_print(s, sl, "%u", (unsigned)sldns_read_uint32(*d)); 1395fdfb4ba6Ssthen (*d)+=4; 1396fdfb4ba6Ssthen (*dl)-=4; 1397fdfb4ba6Ssthen return w; 1398fdfb4ba6Ssthen } 1399fdfb4ba6Ssthen 1400fdfb4ba6Ssthen int sldns_wire2str_tsigtime_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) 1401fdfb4ba6Ssthen { 1402fdfb4ba6Ssthen /* tsigtime is 48 bits network order unsigned integer */ 1403fdfb4ba6Ssthen int w; 1404fdfb4ba6Ssthen uint64_t tsigtime = 0; 1405fdfb4ba6Ssthen uint64_t d0, d1, d2, d3, d4, d5; 1406fdfb4ba6Ssthen if(*dl < 6) return -1; 1407fdfb4ba6Ssthen d0 = (*d)[0]; /* cast to uint64 for shift operations */ 1408fdfb4ba6Ssthen d1 = (*d)[1]; 1409fdfb4ba6Ssthen d2 = (*d)[2]; 1410fdfb4ba6Ssthen d3 = (*d)[3]; 1411fdfb4ba6Ssthen d4 = (*d)[4]; 1412fdfb4ba6Ssthen d5 = (*d)[5]; 1413fdfb4ba6Ssthen tsigtime = (d0<<40) | (d1<<32) | (d2<<24) | (d3<<16) | (d4<<8) | d5; 1414fdfb4ba6Ssthen #ifndef USE_WINSOCK 1415fdfb4ba6Ssthen w = sldns_str_print(s, sl, "%llu", (long long)tsigtime); 1416fdfb4ba6Ssthen #else 1417fdfb4ba6Ssthen w = sldns_str_print(s, sl, "%I64u", (long long)tsigtime); 1418fdfb4ba6Ssthen #endif 1419fdfb4ba6Ssthen (*d)+=6; 1420fdfb4ba6Ssthen (*dl)-=6; 1421fdfb4ba6Ssthen return w; 1422fdfb4ba6Ssthen } 1423fdfb4ba6Ssthen 1424fdfb4ba6Ssthen int sldns_wire2str_a_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) 1425fdfb4ba6Ssthen { 1426fdfb4ba6Ssthen char buf[32]; 1427fdfb4ba6Ssthen int w; 1428fdfb4ba6Ssthen if(*dl < 4) return -1; 1429fdfb4ba6Ssthen if(!inet_ntop(AF_INET, *d, buf, (socklen_t)sizeof(buf))) 1430fdfb4ba6Ssthen return -1; 1431fdfb4ba6Ssthen w = sldns_str_print(s, sl, "%s", buf); 1432fdfb4ba6Ssthen (*d)+=4; 1433fdfb4ba6Ssthen (*dl)-=4; 1434fdfb4ba6Ssthen return w; 1435fdfb4ba6Ssthen } 1436fdfb4ba6Ssthen 1437fdfb4ba6Ssthen int sldns_wire2str_aaaa_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) 1438fdfb4ba6Ssthen { 1439fdfb4ba6Ssthen #ifdef AF_INET6 1440fdfb4ba6Ssthen char buf[64]; 1441fdfb4ba6Ssthen int w; 1442fdfb4ba6Ssthen if(*dl < 16) return -1; 1443fdfb4ba6Ssthen if(!inet_ntop(AF_INET6, *d, buf, (socklen_t)sizeof(buf))) 1444fdfb4ba6Ssthen return -1; 1445fdfb4ba6Ssthen w = sldns_str_print(s, sl, "%s", buf); 1446fdfb4ba6Ssthen (*d)+=16; 1447fdfb4ba6Ssthen (*dl)-=16; 1448fdfb4ba6Ssthen return w; 1449fdfb4ba6Ssthen #else 1450fdfb4ba6Ssthen return -1; 1451fdfb4ba6Ssthen #endif 1452fdfb4ba6Ssthen } 1453fdfb4ba6Ssthen 1454fdfb4ba6Ssthen /** printout escaped TYPE_STR character */ 1455fdfb4ba6Ssthen static int str_char_print(char** s, size_t* sl, uint8_t c) 1456fdfb4ba6Ssthen { 1457fdfb4ba6Ssthen if(isprint((unsigned char)c) || c == '\t') { 1458fdfb4ba6Ssthen if(c == '\"' || c == '\\') 1459fdfb4ba6Ssthen return sldns_str_print(s, sl, "\\%c", c); 1460fdfb4ba6Ssthen if(*sl) { 1461fdfb4ba6Ssthen **s = (char)c; 1462fdfb4ba6Ssthen (*s)++; 1463fdfb4ba6Ssthen (*sl)--; 1464fdfb4ba6Ssthen } 1465fdfb4ba6Ssthen return 1; 1466fdfb4ba6Ssthen } 1467fdfb4ba6Ssthen return sldns_str_print(s, sl, "\\%03u", (unsigned)c); 1468fdfb4ba6Ssthen } 1469fdfb4ba6Ssthen 1470fdfb4ba6Ssthen int sldns_wire2str_str_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) 1471fdfb4ba6Ssthen { 1472fdfb4ba6Ssthen int w = 0; 1473fdfb4ba6Ssthen size_t i, len; 1474fdfb4ba6Ssthen if(*dl < 1) return -1; 1475fdfb4ba6Ssthen len = **d; 1476fdfb4ba6Ssthen if(*dl < 1+len) return -1; 1477fdfb4ba6Ssthen (*d)++; 1478fdfb4ba6Ssthen (*dl)--; 1479fdfb4ba6Ssthen w += sldns_str_print(s, sl, "\""); 1480fdfb4ba6Ssthen for(i=0; i<len; i++) 1481fdfb4ba6Ssthen w += str_char_print(s, sl, (*d)[i]); 1482fdfb4ba6Ssthen w += sldns_str_print(s, sl, "\""); 1483fdfb4ba6Ssthen (*d)+=len; 1484fdfb4ba6Ssthen (*dl)-=len; 1485fdfb4ba6Ssthen return w; 1486fdfb4ba6Ssthen } 1487fdfb4ba6Ssthen 1488fdfb4ba6Ssthen int sldns_wire2str_apl_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) 1489fdfb4ba6Ssthen { 1490fdfb4ba6Ssthen int i, w = 0; 1491fdfb4ba6Ssthen uint16_t family; 1492fdfb4ba6Ssthen uint8_t negation, prefix, adflength; 1493fdfb4ba6Ssthen if(*dl < 4) return -1; 1494fdfb4ba6Ssthen family = sldns_read_uint16(*d); 1495fdfb4ba6Ssthen prefix = (*d)[2]; 1496fdfb4ba6Ssthen negation = ((*d)[3] & LDNS_APL_NEGATION); 1497fdfb4ba6Ssthen adflength = ((*d)[3] & LDNS_APL_MASK); 1498fdfb4ba6Ssthen if(*dl < 4+(size_t)adflength) return -1; 1499fdfb4ba6Ssthen if(family != LDNS_APL_IP4 && family != LDNS_APL_IP6) 1500fdfb4ba6Ssthen return -1; /* unknown address family */ 1501fdfb4ba6Ssthen if(negation) 1502fdfb4ba6Ssthen w += sldns_str_print(s, sl, "!"); 1503fdfb4ba6Ssthen w += sldns_str_print(s, sl, "%u:", (unsigned)family); 1504fdfb4ba6Ssthen if(family == LDNS_APL_IP4) { 1505fdfb4ba6Ssthen /* check if prefix <32 ? */ 1506fdfb4ba6Ssthen /* address is variable length 0 - 4 */ 1507fdfb4ba6Ssthen for(i=0; i<4; i++) { 1508fdfb4ba6Ssthen if(i > 0) 1509fdfb4ba6Ssthen w += sldns_str_print(s, sl, "."); 1510fdfb4ba6Ssthen if(i < (int)adflength) 1511fdfb4ba6Ssthen w += sldns_str_print(s, sl, "%d", (*d)[4+i]); 1512fdfb4ba6Ssthen else w += sldns_str_print(s, sl, "0"); 1513fdfb4ba6Ssthen } 1514fdfb4ba6Ssthen } else if(family == LDNS_APL_IP6) { 1515fdfb4ba6Ssthen /* check if prefix <128 ? */ 1516fdfb4ba6Ssthen /* address is variable length 0 - 16 */ 1517fdfb4ba6Ssthen for(i=0; i<16; i++) { 1518fdfb4ba6Ssthen if(i%2 == 0 && i>0) 1519fdfb4ba6Ssthen w += sldns_str_print(s, sl, ":"); 1520fdfb4ba6Ssthen if(i < (int)adflength) 1521fdfb4ba6Ssthen w += sldns_str_print(s, sl, "%02x", (*d)[4+i]); 1522fdfb4ba6Ssthen else w += sldns_str_print(s, sl, "00"); 1523fdfb4ba6Ssthen } 1524fdfb4ba6Ssthen } 1525fdfb4ba6Ssthen w += sldns_str_print(s, sl, "/%u", (unsigned)prefix); 1526fdfb4ba6Ssthen (*d) += 4+adflength; 1527fdfb4ba6Ssthen (*dl) -= 4+adflength; 1528fdfb4ba6Ssthen return w; 1529fdfb4ba6Ssthen } 1530fdfb4ba6Ssthen 1531fdfb4ba6Ssthen int sldns_wire2str_b32_ext_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) 1532fdfb4ba6Ssthen { 1533fdfb4ba6Ssthen size_t datalen; 1534fdfb4ba6Ssthen size_t sz; 1535fdfb4ba6Ssthen if(*dl < 1) return -1; 1536fdfb4ba6Ssthen datalen = (*d)[0]; 1537fdfb4ba6Ssthen if(*dl < 1+datalen) return -1; 1538fdfb4ba6Ssthen sz = sldns_b32_ntop_calculate_size(datalen); 1539fdfb4ba6Ssthen if(*sl < sz+1) { 1540fdfb4ba6Ssthen (*d) += datalen+1; 1541fdfb4ba6Ssthen (*dl) -= (datalen+1); 1542fdfb4ba6Ssthen return (int)sz; /* out of space really, but would need buffer 1543fdfb4ba6Ssthen in order to truncate the output */ 1544fdfb4ba6Ssthen } 1545fdfb4ba6Ssthen sldns_b32_ntop_extended_hex((*d)+1, datalen, *s, *sl); 1546fdfb4ba6Ssthen (*d) += datalen+1; 1547fdfb4ba6Ssthen (*dl) -= (datalen+1); 1548fdfb4ba6Ssthen (*s) += sz; 1549fdfb4ba6Ssthen (*sl) -= sz; 1550fdfb4ba6Ssthen return (int)sz; 1551fdfb4ba6Ssthen } 1552fdfb4ba6Ssthen 1553fdfb4ba6Ssthen /** scan number of bytes from wire into b64 presentation format */ 1554fdfb4ba6Ssthen static int sldns_wire2str_b64_scan_num(uint8_t** d, size_t* dl, char** s, 1555fdfb4ba6Ssthen size_t* sl, size_t num) 1556fdfb4ba6Ssthen { 1557fdfb4ba6Ssthen /* b64_ntop_calculate size includes null at the end */ 1558fdfb4ba6Ssthen size_t sz = sldns_b64_ntop_calculate_size(num)-1; 1559fdfb4ba6Ssthen if(*sl < sz+1) { 1560fdfb4ba6Ssthen (*d) += num; 1561fdfb4ba6Ssthen (*dl) -= num; 1562fdfb4ba6Ssthen return (int)sz; /* out of space really, but would need buffer 1563fdfb4ba6Ssthen in order to truncate the output */ 1564fdfb4ba6Ssthen } 1565fdfb4ba6Ssthen sldns_b64_ntop(*d, num, *s, *sl); 1566fdfb4ba6Ssthen (*d) += num; 1567fdfb4ba6Ssthen (*dl) -= num; 1568fdfb4ba6Ssthen (*s) += sz; 1569fdfb4ba6Ssthen (*sl) -= sz; 1570fdfb4ba6Ssthen return (int)sz; 1571fdfb4ba6Ssthen } 1572fdfb4ba6Ssthen 1573fdfb4ba6Ssthen int sldns_wire2str_b64_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) 1574fdfb4ba6Ssthen { 15757191de28Ssthen if(*dl == 0) { 15767191de28Ssthen return sldns_str_print(s, sl, "0"); 15777191de28Ssthen } 1578fdfb4ba6Ssthen return sldns_wire2str_b64_scan_num(d, dl, s, sl, *dl); 1579fdfb4ba6Ssthen } 1580fdfb4ba6Ssthen 1581fdfb4ba6Ssthen int sldns_wire2str_hex_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) 1582fdfb4ba6Ssthen { 15837191de28Ssthen if(*dl == 0) { 15847191de28Ssthen return sldns_str_print(s, sl, "0"); 15857191de28Ssthen } 1586fdfb4ba6Ssthen return print_remainder_hex("", d, dl, s, sl); 1587fdfb4ba6Ssthen } 1588fdfb4ba6Ssthen 1589fdfb4ba6Ssthen int sldns_wire2str_nsec_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) 1590fdfb4ba6Ssthen { 1591fdfb4ba6Ssthen uint8_t* p = *d; 1592fdfb4ba6Ssthen size_t pl = *dl; 1593fdfb4ba6Ssthen unsigned i, bit, window, block_len; 1594fdfb4ba6Ssthen uint16_t t; 1595fdfb4ba6Ssthen int w = 0; 1596fdfb4ba6Ssthen 1597fdfb4ba6Ssthen /* check for errors */ 1598fdfb4ba6Ssthen while(pl) { 1599fdfb4ba6Ssthen if(pl < 2) return -1; 1600fdfb4ba6Ssthen block_len = (unsigned)p[1]; 1601fdfb4ba6Ssthen if(pl < 2+block_len) return -1; 1602fdfb4ba6Ssthen p += block_len+2; 1603fdfb4ba6Ssthen pl -= block_len+2; 1604fdfb4ba6Ssthen } 1605fdfb4ba6Ssthen 1606fdfb4ba6Ssthen /* do it */ 1607fdfb4ba6Ssthen p = *d; 1608fdfb4ba6Ssthen pl = *dl; 1609fdfb4ba6Ssthen while(pl) { 1610fdfb4ba6Ssthen if(pl < 2) return -1; /* cannot happen */ 1611fdfb4ba6Ssthen window = (unsigned)p[0]; 1612fdfb4ba6Ssthen block_len = (unsigned)p[1]; 1613fdfb4ba6Ssthen if(pl < 2+block_len) return -1; /* cannot happen */ 1614fdfb4ba6Ssthen p += 2; 1615fdfb4ba6Ssthen for(i=0; i<block_len; i++) { 1616fdfb4ba6Ssthen if(p[i] == 0) continue; 1617fdfb4ba6Ssthen /* base type number for this octet */ 1618fdfb4ba6Ssthen t = ((window)<<8) | (i << 3); 1619fdfb4ba6Ssthen for(bit=0; bit<8; bit++) { 1620fdfb4ba6Ssthen if((p[i]&(0x80>>bit))) { 1621fdfb4ba6Ssthen if(w) w += sldns_str_print(s, sl, " "); 1622fdfb4ba6Ssthen w += sldns_wire2str_type_print(s, sl, 1623fdfb4ba6Ssthen t+bit); 1624fdfb4ba6Ssthen } 1625fdfb4ba6Ssthen } 1626fdfb4ba6Ssthen } 1627fdfb4ba6Ssthen p += block_len; 1628fdfb4ba6Ssthen pl -= block_len+2; 1629fdfb4ba6Ssthen } 1630fdfb4ba6Ssthen (*d) += *dl; 1631fdfb4ba6Ssthen (*dl) = 0; 1632fdfb4ba6Ssthen return w; 1633fdfb4ba6Ssthen } 1634fdfb4ba6Ssthen 1635fdfb4ba6Ssthen int sldns_wire2str_nsec3_salt_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) 1636fdfb4ba6Ssthen { 1637fdfb4ba6Ssthen size_t salt_len; 1638fdfb4ba6Ssthen int w; 1639fdfb4ba6Ssthen if(*dl < 1) return -1; 1640fdfb4ba6Ssthen salt_len = (size_t)(*d)[0]; 1641fdfb4ba6Ssthen if(*dl < 1+salt_len) return -1; 1642fdfb4ba6Ssthen (*d)++; 1643fdfb4ba6Ssthen (*dl)--; 1644fdfb4ba6Ssthen if(salt_len == 0) { 1645fdfb4ba6Ssthen return sldns_str_print(s, sl, "-"); 1646fdfb4ba6Ssthen } 1647fdfb4ba6Ssthen w = print_hex_buf(s, sl, *d, salt_len); 1648fdfb4ba6Ssthen (*dl)-=salt_len; 1649fdfb4ba6Ssthen (*d)+=salt_len; 1650fdfb4ba6Ssthen return w; 1651fdfb4ba6Ssthen } 1652fdfb4ba6Ssthen 1653fdfb4ba6Ssthen int sldns_wire2str_cert_alg_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) 1654fdfb4ba6Ssthen { 1655fdfb4ba6Ssthen sldns_lookup_table *lt; 1656fdfb4ba6Ssthen int data, w; 1657fdfb4ba6Ssthen if(*dl < 2) return -1; 1658fdfb4ba6Ssthen data = (int)sldns_read_uint16(*d); 1659fdfb4ba6Ssthen lt = sldns_lookup_by_id(sldns_cert_algorithms, data); 1660fdfb4ba6Ssthen if(lt && lt->name) 1661fdfb4ba6Ssthen w = sldns_str_print(s, sl, "%s", lt->name); 1662fdfb4ba6Ssthen else w = sldns_str_print(s, sl, "%d", data); 1663fdfb4ba6Ssthen (*dl)-=2; 1664fdfb4ba6Ssthen (*d)+=2; 1665fdfb4ba6Ssthen return w; 1666fdfb4ba6Ssthen } 1667fdfb4ba6Ssthen 1668fdfb4ba6Ssthen int sldns_wire2str_alg_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) 1669fdfb4ba6Ssthen { 1670fdfb4ba6Ssthen /* don't use algorithm mnemonics in the presentation format 1671fdfb4ba6Ssthen * this kind of got sneaked into the rfc's */ 1672fdfb4ba6Ssthen return sldns_wire2str_int8_scan(d, dl, s, sl); 1673fdfb4ba6Ssthen } 1674fdfb4ba6Ssthen 1675fdfb4ba6Ssthen int sldns_wire2str_unknown_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) 1676fdfb4ba6Ssthen { 1677fdfb4ba6Ssthen return sldns_wire2str_rdata_unknown_scan(d, dl, s, sl); 1678fdfb4ba6Ssthen } 1679fdfb4ba6Ssthen 1680fdfb4ba6Ssthen int sldns_wire2str_time_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) 1681fdfb4ba6Ssthen { 1682fdfb4ba6Ssthen /* create a YYYYMMDDHHMMSS string if possible */ 1683fdfb4ba6Ssthen struct tm tm; 1684fdfb4ba6Ssthen char date_buf[16]; 1685fdfb4ba6Ssthen uint32_t t; 1686fdfb4ba6Ssthen memset(&tm, 0, sizeof(tm)); 1687fdfb4ba6Ssthen if(*dl < 4) return -1; 1688fdfb4ba6Ssthen t = sldns_read_uint32(*d); 1689fdfb4ba6Ssthen date_buf[15]=0; 1690bdfc4d55Sflorian if(sldns_serial_arithmetics_gmtime_r(t, time(NULL), &tm) && 1691fdfb4ba6Ssthen strftime(date_buf, 15, "%Y%m%d%H%M%S", &tm)) { 1692fdfb4ba6Ssthen (*d) += 4; 1693fdfb4ba6Ssthen (*dl) -= 4; 1694fdfb4ba6Ssthen return sldns_str_print(s, sl, "%s", date_buf); 1695fdfb4ba6Ssthen } 1696fdfb4ba6Ssthen return -1; 1697fdfb4ba6Ssthen } 1698fdfb4ba6Ssthen 1699fdfb4ba6Ssthen static int 1700fdfb4ba6Ssthen loc_cm_print(char** str, size_t* sl, uint8_t mantissa, uint8_t exponent) 1701fdfb4ba6Ssthen { 1702fdfb4ba6Ssthen int w = 0; 1703fdfb4ba6Ssthen uint8_t i; 1704fdfb4ba6Ssthen /* is it 0.<two digits> ? */ 1705fdfb4ba6Ssthen if(exponent < 2) { 1706fdfb4ba6Ssthen if(exponent == 1) 1707fdfb4ba6Ssthen mantissa *= 10; 1708fdfb4ba6Ssthen return sldns_str_print(str, sl, "0.%02ld", (long)mantissa); 1709fdfb4ba6Ssthen } 1710fdfb4ba6Ssthen /* always <digit><string of zeros> */ 1711fdfb4ba6Ssthen w += sldns_str_print(str, sl, "%d", (int)mantissa); 1712fdfb4ba6Ssthen for(i=0; i<exponent-2; i++) 1713fdfb4ba6Ssthen w += sldns_str_print(str, sl, "0"); 1714fdfb4ba6Ssthen return w; 1715fdfb4ba6Ssthen } 1716fdfb4ba6Ssthen 1717fdfb4ba6Ssthen int sldns_wire2str_loc_scan(uint8_t** d, size_t* dl, char** str, size_t* sl) 1718fdfb4ba6Ssthen { 1719fdfb4ba6Ssthen /* we could do checking (ie degrees < 90 etc)? */ 1720fdfb4ba6Ssthen uint8_t version; 1721fdfb4ba6Ssthen uint8_t size; 1722fdfb4ba6Ssthen uint8_t horizontal_precision; 1723fdfb4ba6Ssthen uint8_t vertical_precision; 1724fdfb4ba6Ssthen uint32_t longitude; 1725fdfb4ba6Ssthen uint32_t latitude; 1726fdfb4ba6Ssthen uint32_t altitude; 1727fdfb4ba6Ssthen char northerness; 1728fdfb4ba6Ssthen char easterness; 1729fdfb4ba6Ssthen uint32_t h; 1730fdfb4ba6Ssthen uint32_t m; 1731fdfb4ba6Ssthen double s; 1732fdfb4ba6Ssthen uint32_t equator = (uint32_t)1 << 31; /* 2**31 */ 1733fdfb4ba6Ssthen int w = 0; 1734fdfb4ba6Ssthen 1735fdfb4ba6Ssthen if(*dl < 16) return -1; 1736fdfb4ba6Ssthen version = (*d)[0]; 1737fdfb4ba6Ssthen if(version != 0) 1738fdfb4ba6Ssthen return sldns_wire2str_hex_scan(d, dl, str, sl); 1739fdfb4ba6Ssthen size = (*d)[1]; 1740fdfb4ba6Ssthen horizontal_precision = (*d)[2]; 1741fdfb4ba6Ssthen vertical_precision = (*d)[3]; 1742fdfb4ba6Ssthen 1743fdfb4ba6Ssthen latitude = sldns_read_uint32((*d)+4); 1744fdfb4ba6Ssthen longitude = sldns_read_uint32((*d)+8); 1745fdfb4ba6Ssthen altitude = sldns_read_uint32((*d)+12); 1746fdfb4ba6Ssthen 1747fdfb4ba6Ssthen if (latitude > equator) { 1748fdfb4ba6Ssthen northerness = 'N'; 1749fdfb4ba6Ssthen latitude = latitude - equator; 1750fdfb4ba6Ssthen } else { 1751fdfb4ba6Ssthen northerness = 'S'; 1752fdfb4ba6Ssthen latitude = equator - latitude; 1753fdfb4ba6Ssthen } 1754fdfb4ba6Ssthen h = latitude / (1000 * 60 * 60); 1755fdfb4ba6Ssthen latitude = latitude % (1000 * 60 * 60); 1756fdfb4ba6Ssthen m = latitude / (1000 * 60); 1757fdfb4ba6Ssthen latitude = latitude % (1000 * 60); 1758fdfb4ba6Ssthen s = (double) latitude / 1000.0; 1759fdfb4ba6Ssthen w += sldns_str_print(str, sl, "%02u %02u %06.3f %c ", 1760fdfb4ba6Ssthen h, m, s, northerness); 1761fdfb4ba6Ssthen 1762fdfb4ba6Ssthen if (longitude > equator) { 1763fdfb4ba6Ssthen easterness = 'E'; 1764fdfb4ba6Ssthen longitude = longitude - equator; 1765fdfb4ba6Ssthen } else { 1766fdfb4ba6Ssthen easterness = 'W'; 1767fdfb4ba6Ssthen longitude = equator - longitude; 1768fdfb4ba6Ssthen } 1769fdfb4ba6Ssthen h = longitude / (1000 * 60 * 60); 1770fdfb4ba6Ssthen longitude = longitude % (1000 * 60 * 60); 1771fdfb4ba6Ssthen m = longitude / (1000 * 60); 1772fdfb4ba6Ssthen longitude = longitude % (1000 * 60); 1773fdfb4ba6Ssthen s = (double) longitude / (1000.0); 1774fdfb4ba6Ssthen w += sldns_str_print(str, sl, "%02u %02u %06.3f %c ", 1775fdfb4ba6Ssthen h, m, s, easterness); 1776fdfb4ba6Ssthen 1777fdfb4ba6Ssthen s = ((double) altitude) / 100; 1778fdfb4ba6Ssthen s -= 100000; 1779fdfb4ba6Ssthen 1780fdfb4ba6Ssthen if(altitude%100 != 0) 1781fdfb4ba6Ssthen w += sldns_str_print(str, sl, "%.2f", s); 1782fdfb4ba6Ssthen else 1783fdfb4ba6Ssthen w += sldns_str_print(str, sl, "%.0f", s); 1784fdfb4ba6Ssthen 1785fdfb4ba6Ssthen w += sldns_str_print(str, sl, "m "); 1786fdfb4ba6Ssthen 1787fdfb4ba6Ssthen w += loc_cm_print(str, sl, (size & 0xf0) >> 4, size & 0x0f); 1788fdfb4ba6Ssthen w += sldns_str_print(str, sl, "m "); 1789fdfb4ba6Ssthen 1790fdfb4ba6Ssthen w += loc_cm_print(str, sl, (horizontal_precision & 0xf0) >> 4, 1791fdfb4ba6Ssthen horizontal_precision & 0x0f); 1792fdfb4ba6Ssthen w += sldns_str_print(str, sl, "m "); 1793fdfb4ba6Ssthen 1794fdfb4ba6Ssthen w += loc_cm_print(str, sl, (vertical_precision & 0xf0) >> 4, 1795fdfb4ba6Ssthen vertical_precision & 0x0f); 1796fdfb4ba6Ssthen w += sldns_str_print(str, sl, "m"); 1797fdfb4ba6Ssthen 1798fdfb4ba6Ssthen (*d)+=16; 1799fdfb4ba6Ssthen (*dl)-=16; 1800fdfb4ba6Ssthen return w; 1801fdfb4ba6Ssthen } 1802fdfb4ba6Ssthen 1803fdfb4ba6Ssthen int sldns_wire2str_wks_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) 1804fdfb4ba6Ssthen { 1805fdfb4ba6Ssthen /* protocol, followed by bitmap of services */ 1806fdfb4ba6Ssthen const char* proto_name = NULL; 1807fdfb4ba6Ssthen struct protoent *protocol; 1808fdfb4ba6Ssthen struct servent *service; 1809fdfb4ba6Ssthen uint8_t protocol_nr; 1810fdfb4ba6Ssthen int bit, port, w = 0; 1811fdfb4ba6Ssthen size_t i; 1812fdfb4ba6Ssthen /* we cannot print with strings because they 1813fdfb4ba6Ssthen * are not portable, the presentation format may 1814fdfb4ba6Ssthen * not be able to be read in on another computer. */ 1815fdfb4ba6Ssthen int print_symbols = 0; 1816fdfb4ba6Ssthen 1817fdfb4ba6Ssthen /* protocol */ 1818fdfb4ba6Ssthen if(*dl < 1) return -1; 1819fdfb4ba6Ssthen protocol_nr = (*d)[0]; 1820fdfb4ba6Ssthen (*d)++; 1821fdfb4ba6Ssthen (*dl)--; 1822fdfb4ba6Ssthen protocol = getprotobynumber((int)protocol_nr); 1823fdfb4ba6Ssthen if(protocol && (protocol->p_name != NULL)) { 1824fdfb4ba6Ssthen w += sldns_str_print(s, sl, "%s", protocol->p_name); 1825fdfb4ba6Ssthen proto_name = protocol->p_name; 18267191de28Ssthen } else if(protocol_nr == 6) { 18277191de28Ssthen w += sldns_str_print(s, sl, "tcp"); 18287191de28Ssthen } else if(protocol_nr == 17) { 18297191de28Ssthen w += sldns_str_print(s, sl, "udp"); 1830fdfb4ba6Ssthen } else { 1831fdfb4ba6Ssthen w += sldns_str_print(s, sl, "%u", (unsigned)protocol_nr); 1832fdfb4ba6Ssthen } 1833fdfb4ba6Ssthen 1834fdfb4ba6Ssthen for(i=0; i<*dl; i++) { 1835fdfb4ba6Ssthen if((*d)[i] == 0) 1836fdfb4ba6Ssthen continue; 1837fdfb4ba6Ssthen for(bit=0; bit<8; bit++) { 1838fdfb4ba6Ssthen if(!(((*d)[i])&(0x80>>bit))) 1839fdfb4ba6Ssthen continue; 1840fdfb4ba6Ssthen port = (int)i*8 + bit; 1841fdfb4ba6Ssthen 1842fdfb4ba6Ssthen if(!print_symbols) 1843fdfb4ba6Ssthen service = NULL; 1844fdfb4ba6Ssthen else 1845fdfb4ba6Ssthen service = getservbyport( 1846fdfb4ba6Ssthen (int)htons((uint16_t)port), proto_name); 1847fdfb4ba6Ssthen if(service && service->s_name) 1848fdfb4ba6Ssthen w += sldns_str_print(s, sl, " %s", 1849fdfb4ba6Ssthen service->s_name); 1850fdfb4ba6Ssthen else w += sldns_str_print(s, sl, " %u", 1851fdfb4ba6Ssthen (unsigned)port); 1852fdfb4ba6Ssthen } 1853fdfb4ba6Ssthen } 1854fdfb4ba6Ssthen 1855fdfb4ba6Ssthen #ifdef HAVE_ENDSERVENT 1856fdfb4ba6Ssthen endservent(); 1857fdfb4ba6Ssthen #endif 1858fdfb4ba6Ssthen #ifdef HAVE_ENDPROTOENT 1859fdfb4ba6Ssthen endprotoent(); 1860fdfb4ba6Ssthen #endif 1861fdfb4ba6Ssthen (*d) += *dl; 1862fdfb4ba6Ssthen (*dl) = 0; 1863fdfb4ba6Ssthen return w; 1864fdfb4ba6Ssthen } 1865fdfb4ba6Ssthen 1866fdfb4ba6Ssthen int sldns_wire2str_nsap_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) 1867fdfb4ba6Ssthen { 1868fdfb4ba6Ssthen return print_remainder_hex("0x", d, dl, s, sl); 1869fdfb4ba6Ssthen } 1870fdfb4ba6Ssthen 1871fdfb4ba6Ssthen int sldns_wire2str_atma_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) 1872fdfb4ba6Ssthen { 1873fdfb4ba6Ssthen return print_remainder_hex("", d, dl, s, sl); 1874fdfb4ba6Ssthen } 1875fdfb4ba6Ssthen 1876fdfb4ba6Ssthen /* internal scan routine that can modify arguments on failure */ 1877fdfb4ba6Ssthen static int sldns_wire2str_ipseckey_scan_internal(uint8_t** d, size_t* dl, 1878ebf5bb73Ssthen char** s, size_t* sl, uint8_t* pkt, size_t pktlen, int* comprloop) 1879fdfb4ba6Ssthen { 1880fdfb4ba6Ssthen /* http://www.ietf.org/internet-drafts/draft-ietf-ipseckey-rr-12.txt*/ 1881fdfb4ba6Ssthen uint8_t precedence, gateway_type, algorithm; 1882fdfb4ba6Ssthen int w = 0; 1883fdfb4ba6Ssthen 1884fdfb4ba6Ssthen if(*dl < 3) return -1; 1885fdfb4ba6Ssthen precedence = (*d)[0]; 1886fdfb4ba6Ssthen gateway_type = (*d)[1]; 1887fdfb4ba6Ssthen algorithm = (*d)[2]; 1888fdfb4ba6Ssthen if(gateway_type > 3) 1889fdfb4ba6Ssthen return -1; /* unknown */ 1890fdfb4ba6Ssthen (*d)+=3; 1891fdfb4ba6Ssthen (*dl)-=3; 1892fdfb4ba6Ssthen w += sldns_str_print(s, sl, "%d %d %d ", 1893fdfb4ba6Ssthen (int)precedence, (int)gateway_type, (int)algorithm); 1894fdfb4ba6Ssthen 1895fdfb4ba6Ssthen switch(gateway_type) { 1896fdfb4ba6Ssthen case 0: /* no gateway */ 1897fdfb4ba6Ssthen w += sldns_str_print(s, sl, "."); 1898fdfb4ba6Ssthen break; 1899fdfb4ba6Ssthen case 1: /* ip4 */ 1900fdfb4ba6Ssthen w += sldns_wire2str_a_scan(d, dl, s, sl); 1901fdfb4ba6Ssthen break; 1902fdfb4ba6Ssthen case 2: /* ip6 */ 1903fdfb4ba6Ssthen w += sldns_wire2str_aaaa_scan(d, dl, s, sl); 1904fdfb4ba6Ssthen break; 1905fdfb4ba6Ssthen case 3: /* dname */ 1906ebf5bb73Ssthen w += sldns_wire2str_dname_scan(d, dl, s, sl, pkt, pktlen, comprloop); 1907fdfb4ba6Ssthen break; 1908fdfb4ba6Ssthen default: /* unknown */ 1909fdfb4ba6Ssthen return -1; 1910fdfb4ba6Ssthen } 1911fdfb4ba6Ssthen 1912fdfb4ba6Ssthen if(*dl < 1) 1913fdfb4ba6Ssthen return -1; 1914fdfb4ba6Ssthen w += sldns_str_print(s, sl, " "); 1915fdfb4ba6Ssthen w += sldns_wire2str_b64_scan_num(d, dl, s, sl, *dl); 1916fdfb4ba6Ssthen return w; 1917fdfb4ba6Ssthen } 1918fdfb4ba6Ssthen 1919fdfb4ba6Ssthen int sldns_wire2str_ipseckey_scan(uint8_t** d, size_t* dl, char** s, size_t* sl, 1920ebf5bb73Ssthen uint8_t* pkt, size_t pktlen, int* comprloop) 1921fdfb4ba6Ssthen { 1922fdfb4ba6Ssthen uint8_t* od = *d; 1923fdfb4ba6Ssthen char* os = *s; 1924fdfb4ba6Ssthen size_t odl = *dl, osl = *sl; 1925ebf5bb73Ssthen int w=sldns_wire2str_ipseckey_scan_internal(d, dl, s, sl, pkt, pktlen, comprloop); 1926fdfb4ba6Ssthen if(w == -1) { 1927fdfb4ba6Ssthen *d = od; 1928fdfb4ba6Ssthen *s = os; 1929fdfb4ba6Ssthen *dl = odl; 1930fdfb4ba6Ssthen *sl = osl; 1931fdfb4ba6Ssthen return -1; 1932fdfb4ba6Ssthen } 1933fdfb4ba6Ssthen return w; 1934fdfb4ba6Ssthen } 1935fdfb4ba6Ssthen 1936fdfb4ba6Ssthen int sldns_wire2str_hip_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) 1937fdfb4ba6Ssthen { 1938fdfb4ba6Ssthen int w; 1939fdfb4ba6Ssthen uint8_t algo, hitlen; 1940fdfb4ba6Ssthen uint16_t pklen; 1941fdfb4ba6Ssthen 1942fdfb4ba6Ssthen /* read lengths */ 1943fdfb4ba6Ssthen if(*dl < 4) 1944fdfb4ba6Ssthen return -1; 1945fdfb4ba6Ssthen hitlen = (*d)[0]; 1946fdfb4ba6Ssthen algo = (*d)[1]; 1947fdfb4ba6Ssthen pklen = sldns_read_uint16((*d)+2); 1948fdfb4ba6Ssthen if(*dl < (size_t)4 + (size_t)hitlen + (size_t)pklen) 1949fdfb4ba6Ssthen return -1; 1950fdfb4ba6Ssthen 1951fdfb4ba6Ssthen /* write: algo hit pubkey */ 1952fdfb4ba6Ssthen w = sldns_str_print(s, sl, "%u ", (unsigned)algo); 1953fdfb4ba6Ssthen w += print_hex_buf(s, sl, (*d)+4, hitlen); 1954fdfb4ba6Ssthen w += sldns_str_print(s, sl, " "); 1955fdfb4ba6Ssthen (*d)+=4+hitlen; 1956fdfb4ba6Ssthen (*dl)-= (4+hitlen); 1957fdfb4ba6Ssthen w += sldns_wire2str_b64_scan_num(d, dl, s, sl, pklen); 1958fdfb4ba6Ssthen return w; 1959fdfb4ba6Ssthen } 1960fdfb4ba6Ssthen 1961fdfb4ba6Ssthen int sldns_wire2str_int16_data_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) 1962fdfb4ba6Ssthen { 19632be9e038Ssthen int w; 1964fdfb4ba6Ssthen uint16_t n; 1965fdfb4ba6Ssthen if(*dl < 2) 1966fdfb4ba6Ssthen return -1; 1967fdfb4ba6Ssthen n = sldns_read_uint16(*d); 1968fdfb4ba6Ssthen if(*dl < 2+(size_t)n) 1969fdfb4ba6Ssthen return -1; 1970fdfb4ba6Ssthen (*d)+=2; 1971fdfb4ba6Ssthen (*dl)-=2; 19722be9e038Ssthen if(n == 0) { 19732be9e038Ssthen return sldns_str_print(s, sl, "0"); 19742be9e038Ssthen } 19752be9e038Ssthen w = sldns_str_print(s, sl, "%u ", (unsigned)n); 19762be9e038Ssthen w += sldns_wire2str_b64_scan_num(d, dl, s, sl, n); 19772be9e038Ssthen return w; 1978fdfb4ba6Ssthen } 1979fdfb4ba6Ssthen 1980fdfb4ba6Ssthen int sldns_wire2str_nsec3_next_owner_scan(uint8_t** d, size_t* dl, char** s, 1981fdfb4ba6Ssthen size_t* sl) 1982fdfb4ba6Ssthen { 1983fdfb4ba6Ssthen return sldns_wire2str_b32_ext_scan(d, dl, s, sl); 1984fdfb4ba6Ssthen } 1985fdfb4ba6Ssthen 1986fdfb4ba6Ssthen int sldns_wire2str_ilnp64_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) 1987fdfb4ba6Ssthen { 1988fdfb4ba6Ssthen int w; 1989fdfb4ba6Ssthen if(*dl < 8) 1990fdfb4ba6Ssthen return -1; 1991fdfb4ba6Ssthen w = sldns_str_print(s, sl, "%.4x:%.4x:%.4x:%.4x", 1992fdfb4ba6Ssthen sldns_read_uint16(*d), sldns_read_uint16((*d)+2), 1993fdfb4ba6Ssthen sldns_read_uint16((*d)+4), sldns_read_uint16((*d)+6)); 1994fdfb4ba6Ssthen (*d)+=8; 1995fdfb4ba6Ssthen (*dl)-=8; 1996fdfb4ba6Ssthen return w; 1997fdfb4ba6Ssthen } 1998fdfb4ba6Ssthen 1999fdfb4ba6Ssthen int sldns_wire2str_eui48_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) 2000fdfb4ba6Ssthen { 2001fdfb4ba6Ssthen int w; 2002fdfb4ba6Ssthen if(*dl < 6) 2003fdfb4ba6Ssthen return -1; 2004fdfb4ba6Ssthen w = sldns_str_print(s, sl, "%.2x-%.2x-%.2x-%.2x-%.2x-%.2x", 2005fdfb4ba6Ssthen (*d)[0], (*d)[1], (*d)[2], (*d)[3], (*d)[4], (*d)[5]); 2006fdfb4ba6Ssthen (*d)+=6; 2007fdfb4ba6Ssthen (*dl)-=6; 2008fdfb4ba6Ssthen return w; 2009fdfb4ba6Ssthen } 2010fdfb4ba6Ssthen 2011fdfb4ba6Ssthen int sldns_wire2str_eui64_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) 2012fdfb4ba6Ssthen { 2013fdfb4ba6Ssthen int w; 2014fdfb4ba6Ssthen if(*dl < 8) 2015fdfb4ba6Ssthen return -1; 2016fdfb4ba6Ssthen w = sldns_str_print(s, sl, "%.2x-%.2x-%.2x-%.2x-%.2x-%.2x-%.2x-%.2x", 2017fdfb4ba6Ssthen (*d)[0], (*d)[1], (*d)[2], (*d)[3], (*d)[4], (*d)[5], 2018fdfb4ba6Ssthen (*d)[6], (*d)[7]); 2019fdfb4ba6Ssthen (*d)+=8; 2020fdfb4ba6Ssthen (*dl)-=8; 2021fdfb4ba6Ssthen return w; 2022fdfb4ba6Ssthen } 2023fdfb4ba6Ssthen 2024fdfb4ba6Ssthen int sldns_wire2str_tag_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) 2025fdfb4ba6Ssthen { 2026fdfb4ba6Ssthen size_t i, n; 2027fdfb4ba6Ssthen int w = 0; 2028fdfb4ba6Ssthen if(*dl < 1) 2029fdfb4ba6Ssthen return -1; 2030fdfb4ba6Ssthen n = (size_t)((*d)[0]); 2031fdfb4ba6Ssthen if(*dl < 1+n) 2032fdfb4ba6Ssthen return -1; 2033fdfb4ba6Ssthen for(i=0; i<n; i++) 20342be9e038Ssthen if(!isalnum((unsigned char)(*d)[i+1])) 2035fdfb4ba6Ssthen return -1; 2036fdfb4ba6Ssthen for(i=0; i<n; i++) 20372be9e038Ssthen w += sldns_str_print(s, sl, "%c", (char)(*d)[i+1]); 2038fdfb4ba6Ssthen (*d)+=n+1; 2039fdfb4ba6Ssthen (*dl)-=(n+1); 2040fdfb4ba6Ssthen return w; 2041fdfb4ba6Ssthen } 2042fdfb4ba6Ssthen 2043fdfb4ba6Ssthen int sldns_wire2str_long_str_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) 2044fdfb4ba6Ssthen { 2045fdfb4ba6Ssthen size_t i; 2046fdfb4ba6Ssthen int w = 0; 2047fdfb4ba6Ssthen w += sldns_str_print(s, sl, "\""); 2048fdfb4ba6Ssthen for(i=0; i<*dl; i++) 2049fdfb4ba6Ssthen w += str_char_print(s, sl, (*d)[i]); 2050fdfb4ba6Ssthen w += sldns_str_print(s, sl, "\""); 2051fdfb4ba6Ssthen (*d)+=*dl; 2052fdfb4ba6Ssthen (*dl)=0; 2053fdfb4ba6Ssthen return w; 2054fdfb4ba6Ssthen } 2055fdfb4ba6Ssthen 20562be9e038Ssthen int sldns_wire2str_tsigerror_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) 20572be9e038Ssthen { 20582be9e038Ssthen sldns_lookup_table *lt; 20592be9e038Ssthen int data, w; 20602be9e038Ssthen if(*dl < 2) return -1; 20612be9e038Ssthen data = (int)sldns_read_uint16(*d); 20622be9e038Ssthen lt = sldns_lookup_by_id(sldns_tsig_errors, data); 20632be9e038Ssthen if(lt && lt->name) 20642be9e038Ssthen w = sldns_str_print(s, sl, "%s", lt->name); 20652be9e038Ssthen else w = sldns_str_print(s, sl, "%d", data); 20662be9e038Ssthen (*dl)-=2; 20672be9e038Ssthen (*d)+=2; 20682be9e038Ssthen return w; 20692be9e038Ssthen } 20702be9e038Ssthen 2071fdfb4ba6Ssthen int sldns_wire2str_edns_llq_print(char** s, size_t* sl, uint8_t* data, 2072fdfb4ba6Ssthen size_t len) 2073fdfb4ba6Ssthen { 2074fdfb4ba6Ssthen /* LLQ constants */ 2075fdfb4ba6Ssthen const char* llq_errors[] = {"NO-ERROR", "SERV-FULL", "STATIC", 2076fdfb4ba6Ssthen "FORMAT-ERR", "NO-SUCH-LLQ", "BAD-VERS", "UNKNOWN_ERR"}; 2077fdfb4ba6Ssthen const unsigned int llq_errors_num = 7; 2078fdfb4ba6Ssthen const char* llq_opcodes[] = {"LLQ-SETUP", "LLQ-REFRESH", "LLQ-EVENT"}; 2079fdfb4ba6Ssthen const unsigned int llq_opcodes_num = 3; 2080fdfb4ba6Ssthen uint16_t version, llq_opcode, error_code; 2081fdfb4ba6Ssthen uint64_t llq_id; 2082fdfb4ba6Ssthen uint32_t lease_life; /* Requested or granted life of LLQ, in seconds */ 2083fdfb4ba6Ssthen int w = 0; 2084fdfb4ba6Ssthen 2085fdfb4ba6Ssthen /* read the record */ 2086fdfb4ba6Ssthen if(len != 18) { 2087fdfb4ba6Ssthen w += sldns_str_print(s, sl, "malformed LLQ "); 2088fdfb4ba6Ssthen w += print_hex_buf(s, sl, data, len); 2089fdfb4ba6Ssthen return w; 2090fdfb4ba6Ssthen } 2091fdfb4ba6Ssthen version = sldns_read_uint16(data); 2092fdfb4ba6Ssthen llq_opcode = sldns_read_uint16(data+2); 2093fdfb4ba6Ssthen error_code = sldns_read_uint16(data+4); 2094fdfb4ba6Ssthen memmove(&llq_id, data+6, sizeof(llq_id)); 2095fdfb4ba6Ssthen lease_life = sldns_read_uint32(data+14); 2096fdfb4ba6Ssthen 2097fdfb4ba6Ssthen /* print it */ 2098fdfb4ba6Ssthen w += sldns_str_print(s, sl, "v%d ", (int)version); 2099fdfb4ba6Ssthen if(llq_opcode < llq_opcodes_num) 2100fdfb4ba6Ssthen w += sldns_str_print(s, sl, "%s", llq_opcodes[llq_opcode]); 2101fdfb4ba6Ssthen else w += sldns_str_print(s, sl, "opcode %d", (int)llq_opcode); 2102fdfb4ba6Ssthen if(error_code < llq_errors_num) 2103fdfb4ba6Ssthen w += sldns_str_print(s, sl, " %s", llq_errors[error_code]); 2104fdfb4ba6Ssthen else w += sldns_str_print(s, sl, " error %d", (int)error_code); 2105fdfb4ba6Ssthen #ifndef USE_WINSOCK 2106fdfb4ba6Ssthen w += sldns_str_print(s, sl, " id %llx lease-life %lu", 2107fdfb4ba6Ssthen (unsigned long long)llq_id, (unsigned long)lease_life); 2108fdfb4ba6Ssthen #else 2109fdfb4ba6Ssthen w += sldns_str_print(s, sl, " id %I64x lease-life %lu", 2110fdfb4ba6Ssthen (unsigned long long)llq_id, (unsigned long)lease_life); 2111fdfb4ba6Ssthen #endif 2112fdfb4ba6Ssthen return w; 2113fdfb4ba6Ssthen } 2114fdfb4ba6Ssthen 2115fdfb4ba6Ssthen int sldns_wire2str_edns_ul_print(char** s, size_t* sl, uint8_t* data, 2116fdfb4ba6Ssthen size_t len) 2117fdfb4ba6Ssthen { 2118fdfb4ba6Ssthen uint32_t lease; 2119fdfb4ba6Ssthen int w = 0; 2120fdfb4ba6Ssthen if(len != 4) { 2121fdfb4ba6Ssthen w += sldns_str_print(s, sl, "malformed UL "); 2122fdfb4ba6Ssthen w += print_hex_buf(s, sl, data, len); 2123fdfb4ba6Ssthen return w; 2124fdfb4ba6Ssthen } 2125fdfb4ba6Ssthen lease = sldns_read_uint32(data); 2126fdfb4ba6Ssthen w += sldns_str_print(s, sl, "lease %lu", (unsigned long)lease); 2127fdfb4ba6Ssthen return w; 2128fdfb4ba6Ssthen } 2129fdfb4ba6Ssthen 2130fdfb4ba6Ssthen int sldns_wire2str_edns_nsid_print(char** s, size_t* sl, uint8_t* data, 2131fdfb4ba6Ssthen size_t len) 2132fdfb4ba6Ssthen { 2133fdfb4ba6Ssthen int w = 0; 2134fdfb4ba6Ssthen size_t i, printed=0; 2135fdfb4ba6Ssthen w += print_hex_buf(s, sl, data, len); 2136fdfb4ba6Ssthen for(i=0; i<len; i++) { 2137fdfb4ba6Ssthen if(isprint((unsigned char)data[i]) || data[i] == '\t') { 2138fdfb4ba6Ssthen if(!printed) { 2139fdfb4ba6Ssthen w += sldns_str_print(s, sl, " ("); 2140fdfb4ba6Ssthen printed = 1; 2141fdfb4ba6Ssthen } 2142fdfb4ba6Ssthen w += sldns_str_print(s, sl, "%c", (char)data[i]); 2143fdfb4ba6Ssthen } 2144fdfb4ba6Ssthen } 2145fdfb4ba6Ssthen if(printed) 2146fdfb4ba6Ssthen w += sldns_str_print(s, sl, ")"); 2147fdfb4ba6Ssthen return w; 2148fdfb4ba6Ssthen } 2149fdfb4ba6Ssthen 2150fdfb4ba6Ssthen int sldns_wire2str_edns_dau_print(char** s, size_t* sl, uint8_t* data, 2151fdfb4ba6Ssthen size_t len) 2152fdfb4ba6Ssthen { 2153fdfb4ba6Ssthen sldns_lookup_table *lt; 2154fdfb4ba6Ssthen size_t i; 2155fdfb4ba6Ssthen int w = 0; 2156fdfb4ba6Ssthen for(i=0; i<len; i++) { 2157fdfb4ba6Ssthen lt = sldns_lookup_by_id(sldns_algorithms, (int)data[i]); 2158fdfb4ba6Ssthen if(lt && lt->name) 2159fdfb4ba6Ssthen w += sldns_str_print(s, sl, " %s", lt->name); 2160fdfb4ba6Ssthen else w += sldns_str_print(s, sl, " %d", (int)data[i]); 2161fdfb4ba6Ssthen } 2162fdfb4ba6Ssthen return w; 2163fdfb4ba6Ssthen } 2164fdfb4ba6Ssthen 2165fdfb4ba6Ssthen int sldns_wire2str_edns_dhu_print(char** s, size_t* sl, uint8_t* data, 2166fdfb4ba6Ssthen size_t len) 2167fdfb4ba6Ssthen { 2168fdfb4ba6Ssthen sldns_lookup_table *lt; 2169fdfb4ba6Ssthen size_t i; 2170fdfb4ba6Ssthen int w = 0; 2171fdfb4ba6Ssthen for(i=0; i<len; i++) { 2172fdfb4ba6Ssthen lt = sldns_lookup_by_id(sldns_hashes, (int)data[i]); 2173fdfb4ba6Ssthen if(lt && lt->name) 2174fdfb4ba6Ssthen w += sldns_str_print(s, sl, " %s", lt->name); 2175fdfb4ba6Ssthen else w += sldns_str_print(s, sl, " %d", (int)data[i]); 2176fdfb4ba6Ssthen } 2177fdfb4ba6Ssthen return w; 2178fdfb4ba6Ssthen } 2179fdfb4ba6Ssthen 2180fdfb4ba6Ssthen int sldns_wire2str_edns_n3u_print(char** s, size_t* sl, uint8_t* data, 2181fdfb4ba6Ssthen size_t len) 2182fdfb4ba6Ssthen { 2183fdfb4ba6Ssthen size_t i; 2184fdfb4ba6Ssthen int w = 0; 2185fdfb4ba6Ssthen for(i=0; i<len; i++) { 2186fdfb4ba6Ssthen if(data[i] == 1) 2187fdfb4ba6Ssthen w += sldns_str_print(s, sl, " SHA1"); 2188fdfb4ba6Ssthen else w += sldns_str_print(s, sl, " %d", (int)data[i]); 2189fdfb4ba6Ssthen } 2190fdfb4ba6Ssthen return w; 2191fdfb4ba6Ssthen } 2192fdfb4ba6Ssthen 2193fdfb4ba6Ssthen int sldns_wire2str_edns_subnet_print(char** s, size_t* sl, uint8_t* data, 2194fdfb4ba6Ssthen size_t len) 2195fdfb4ba6Ssthen { 2196fdfb4ba6Ssthen int w = 0; 2197fdfb4ba6Ssthen uint16_t family; 2198fdfb4ba6Ssthen uint8_t source, scope; 2199fdfb4ba6Ssthen if(len < 4) { 2200fdfb4ba6Ssthen w += sldns_str_print(s, sl, "malformed subnet "); 2201fdfb4ba6Ssthen w += print_hex_buf(s, sl, data, len); 2202fdfb4ba6Ssthen return w; 2203fdfb4ba6Ssthen } 2204fdfb4ba6Ssthen family = sldns_read_uint16(data); 2205fdfb4ba6Ssthen source = data[2]; 2206fdfb4ba6Ssthen scope = data[3]; 2207fdfb4ba6Ssthen if(family == 1) { 2208fdfb4ba6Ssthen /* IP4 */ 2209fdfb4ba6Ssthen char buf[64]; 2210fdfb4ba6Ssthen uint8_t ip4[4]; 2211fdfb4ba6Ssthen memset(ip4, 0, sizeof(ip4)); 2212fdfb4ba6Ssthen if(len-4 > 4) { 2213fdfb4ba6Ssthen w += sldns_str_print(s, sl, "trailingdata:"); 2214fdfb4ba6Ssthen w += print_hex_buf(s, sl, data+4+4, len-4-4); 2215fdfb4ba6Ssthen w += sldns_str_print(s, sl, " "); 2216fdfb4ba6Ssthen len = 4+4; 2217fdfb4ba6Ssthen } 2218fdfb4ba6Ssthen memmove(ip4, data+4, len-4); 2219fdfb4ba6Ssthen if(!inet_ntop(AF_INET, ip4, buf, (socklen_t)sizeof(buf))) { 2220fdfb4ba6Ssthen w += sldns_str_print(s, sl, "ip4ntoperror "); 2221fdfb4ba6Ssthen w += print_hex_buf(s, sl, data+4+4, len-4-4); 2222fdfb4ba6Ssthen } else { 2223fdfb4ba6Ssthen w += sldns_str_print(s, sl, "%s", buf); 2224fdfb4ba6Ssthen } 2225fdfb4ba6Ssthen } else if(family == 2) { 2226fdfb4ba6Ssthen /* IP6 */ 2227fdfb4ba6Ssthen char buf[64]; 2228fdfb4ba6Ssthen uint8_t ip6[16]; 2229fdfb4ba6Ssthen memset(ip6, 0, sizeof(ip6)); 2230fdfb4ba6Ssthen if(len-4 > 16) { 2231fdfb4ba6Ssthen w += sldns_str_print(s, sl, "trailingdata:"); 2232fdfb4ba6Ssthen w += print_hex_buf(s, sl, data+4+16, len-4-16); 2233fdfb4ba6Ssthen w += sldns_str_print(s, sl, " "); 2234fdfb4ba6Ssthen len = 4+16; 2235fdfb4ba6Ssthen } 2236fdfb4ba6Ssthen memmove(ip6, data+4, len-4); 2237fdfb4ba6Ssthen #ifdef AF_INET6 2238fdfb4ba6Ssthen if(!inet_ntop(AF_INET6, ip6, buf, (socklen_t)sizeof(buf))) { 2239fdfb4ba6Ssthen w += sldns_str_print(s, sl, "ip6ntoperror "); 2240fdfb4ba6Ssthen w += print_hex_buf(s, sl, data+4+4, len-4-4); 2241fdfb4ba6Ssthen } else { 2242fdfb4ba6Ssthen w += sldns_str_print(s, sl, "%s", buf); 2243fdfb4ba6Ssthen } 2244fdfb4ba6Ssthen #else 2245fdfb4ba6Ssthen w += print_hex_buf(s, sl, data+4+4, len-4-4); 2246fdfb4ba6Ssthen #endif 2247fdfb4ba6Ssthen } else { 2248fdfb4ba6Ssthen /* unknown */ 2249fdfb4ba6Ssthen w += sldns_str_print(s, sl, "family %d ", 2250fdfb4ba6Ssthen (int)family); 2251fdfb4ba6Ssthen w += print_hex_buf(s, sl, data, len); 2252fdfb4ba6Ssthen } 2253fdfb4ba6Ssthen w += sldns_str_print(s, sl, "/%d scope /%d", (int)source, (int)scope); 2254fdfb4ba6Ssthen return w; 2255fdfb4ba6Ssthen } 2256fdfb4ba6Ssthen 2257f6b99bafSsthen static int sldns_wire2str_edns_keepalive_print(char** s, size_t* sl, 2258f6b99bafSsthen uint8_t* data, size_t len) 22592be9e038Ssthen { 22602be9e038Ssthen int w = 0; 22612be9e038Ssthen uint16_t timeout; 22622be9e038Ssthen if(!(len == 0 || len == 2)) { 22632be9e038Ssthen w += sldns_str_print(s, sl, "malformed keepalive "); 22642be9e038Ssthen w += print_hex_buf(s, sl, data, len); 22652be9e038Ssthen return w; 22662be9e038Ssthen } 22672be9e038Ssthen if(len == 0 ) { 22682be9e038Ssthen w += sldns_str_print(s, sl, "no timeout value (only valid for client option) "); 22692be9e038Ssthen } else { 22702be9e038Ssthen timeout = sldns_read_uint16(data); 22712be9e038Ssthen w += sldns_str_print(s, sl, "timeout value in units of 100ms %u", (int)timeout); 22722be9e038Ssthen } 22732be9e038Ssthen return w; 22742be9e038Ssthen } 22752be9e038Ssthen 2276d896b962Ssthen int sldns_wire2str_edns_ede_print(char** s, size_t* sl, 2277d896b962Ssthen uint8_t* data, size_t len) 2278d896b962Ssthen { 2279d896b962Ssthen uint16_t ede_code; 2280d896b962Ssthen int w = 0; 2281d896b962Ssthen sldns_lookup_table *lt; 2282d896b962Ssthen size_t i; 2283d896b962Ssthen int printable; 2284d896b962Ssthen 2285d896b962Ssthen if(len < 2) { 2286d896b962Ssthen w += sldns_str_print(s, sl, "malformed ede "); 2287d896b962Ssthen w += print_hex_buf(s, sl, data, len); 2288d896b962Ssthen return w; 2289d896b962Ssthen } 2290d896b962Ssthen 2291d896b962Ssthen ede_code = sldns_read_uint16(data); 2292d896b962Ssthen lt = sldns_lookup_by_id(sldns_edns_ede_codes, (int)ede_code); 2293d896b962Ssthen if(lt && lt->name) 2294d896b962Ssthen w += sldns_str_print(s, sl, "%s", lt->name); 2295d896b962Ssthen else w += sldns_str_print(s, sl, "%d", (int)ede_code); 2296d896b962Ssthen 2297d896b962Ssthen if(len == 2) 2298d896b962Ssthen return w; 2299d896b962Ssthen 2300d896b962Ssthen w += sldns_str_print(s, sl, " "); 2301d896b962Ssthen 2302d896b962Ssthen /* If it looks like text, show it as text. */ 2303d896b962Ssthen printable=1; 2304d896b962Ssthen for(i=2; i<len; i++) { 2305d896b962Ssthen if(isprint((unsigned char)data[i]) || data[i] == '\t') 2306d896b962Ssthen continue; 2307d896b962Ssthen printable = 0; 2308d896b962Ssthen break; 2309d896b962Ssthen } 2310d896b962Ssthen if(printable) { 2311d896b962Ssthen w += sldns_str_print(s, sl, "\""); 2312d896b962Ssthen for(i=2; i<len; i++) { 2313d896b962Ssthen w += str_char_print(s, sl, data[i]); 2314d896b962Ssthen } 2315d896b962Ssthen w += sldns_str_print(s, sl, "\""); 2316d896b962Ssthen } else { 2317d896b962Ssthen w += print_hex_buf(s, sl, data+2, len-2); 2318d896b962Ssthen } 2319d896b962Ssthen return w; 2320d896b962Ssthen } 2321d896b962Ssthen 2322fdfb4ba6Ssthen int sldns_wire2str_edns_option_print(char** s, size_t* sl, 2323fdfb4ba6Ssthen uint16_t option_code, uint8_t* optdata, size_t optlen) 2324fdfb4ba6Ssthen { 2325fdfb4ba6Ssthen int w = 0; 2326fdfb4ba6Ssthen w += sldns_wire2str_edns_option_code_print(s, sl, option_code); 2327fdfb4ba6Ssthen w += sldns_str_print(s, sl, ": "); 2328fdfb4ba6Ssthen switch(option_code) { 2329fdfb4ba6Ssthen case LDNS_EDNS_LLQ: 2330fdfb4ba6Ssthen w += sldns_wire2str_edns_llq_print(s, sl, optdata, optlen); 2331fdfb4ba6Ssthen break; 2332fdfb4ba6Ssthen case LDNS_EDNS_UL: 2333fdfb4ba6Ssthen w += sldns_wire2str_edns_ul_print(s, sl, optdata, optlen); 2334fdfb4ba6Ssthen break; 2335fdfb4ba6Ssthen case LDNS_EDNS_NSID: 2336fdfb4ba6Ssthen w += sldns_wire2str_edns_nsid_print(s, sl, optdata, optlen); 2337fdfb4ba6Ssthen break; 2338fdfb4ba6Ssthen case LDNS_EDNS_DAU: 2339fdfb4ba6Ssthen w += sldns_wire2str_edns_dau_print(s, sl, optdata, optlen); 2340fdfb4ba6Ssthen break; 2341fdfb4ba6Ssthen case LDNS_EDNS_DHU: 2342fdfb4ba6Ssthen w += sldns_wire2str_edns_dhu_print(s, sl, optdata, optlen); 2343fdfb4ba6Ssthen break; 2344fdfb4ba6Ssthen case LDNS_EDNS_N3U: 2345fdfb4ba6Ssthen w += sldns_wire2str_edns_n3u_print(s, sl, optdata, optlen); 2346fdfb4ba6Ssthen break; 2347fdfb4ba6Ssthen case LDNS_EDNS_CLIENT_SUBNET: 2348fdfb4ba6Ssthen w += sldns_wire2str_edns_subnet_print(s, sl, optdata, optlen); 2349fdfb4ba6Ssthen break; 23502be9e038Ssthen case LDNS_EDNS_KEEPALIVE: 23512be9e038Ssthen w += sldns_wire2str_edns_keepalive_print(s, sl, optdata, optlen); 23522be9e038Ssthen break; 23532ee382b6Ssthen case LDNS_EDNS_PADDING: 23542ee382b6Ssthen w += print_hex_buf(s, sl, optdata, optlen); 23552ee382b6Ssthen break; 2356d896b962Ssthen case LDNS_EDNS_EDE: 2357d896b962Ssthen w += sldns_wire2str_edns_ede_print(s, sl, optdata, optlen); 2358d896b962Ssthen break; 2359fdfb4ba6Ssthen default: 2360fdfb4ba6Ssthen /* unknown option code */ 2361fdfb4ba6Ssthen w += print_hex_buf(s, sl, optdata, optlen); 2362fdfb4ba6Ssthen break; 2363fdfb4ba6Ssthen } 2364fdfb4ba6Ssthen return w; 2365fdfb4ba6Ssthen } 2366fdfb4ba6Ssthen 2367fdfb4ba6Ssthen /** print the edns options to string */ 2368fdfb4ba6Ssthen static int 2369fdfb4ba6Ssthen print_edns_opts(char** s, size_t* sl, uint8_t* rdata, size_t rdatalen) 2370fdfb4ba6Ssthen { 2371fdfb4ba6Ssthen uint16_t option_code, option_len; 2372fdfb4ba6Ssthen int w = 0; 2373fdfb4ba6Ssthen while(rdatalen > 0) { 2374fdfb4ba6Ssthen /* option name */ 2375fdfb4ba6Ssthen if(rdatalen < 4) { 2376fdfb4ba6Ssthen w += sldns_str_print(s, sl, " ; malformed: "); 2377fdfb4ba6Ssthen w += print_hex_buf(s, sl, rdata, rdatalen); 2378fdfb4ba6Ssthen return w; 2379fdfb4ba6Ssthen } 2380fdfb4ba6Ssthen option_code = sldns_read_uint16(rdata); 2381fdfb4ba6Ssthen option_len = sldns_read_uint16(rdata+2); 2382fdfb4ba6Ssthen rdata += 4; 2383fdfb4ba6Ssthen rdatalen -= 4; 2384fdfb4ba6Ssthen 2385fdfb4ba6Ssthen /* option value */ 2386fdfb4ba6Ssthen if(rdatalen < (size_t)option_len) { 2387fdfb4ba6Ssthen w += sldns_str_print(s, sl, " ; malformed "); 2388fdfb4ba6Ssthen w += sldns_wire2str_edns_option_code_print(s, sl, 2389fdfb4ba6Ssthen option_code); 2390fdfb4ba6Ssthen w += sldns_str_print(s, sl, ": "); 2391fdfb4ba6Ssthen w += print_hex_buf(s, sl, rdata, rdatalen); 2392fdfb4ba6Ssthen return w; 2393fdfb4ba6Ssthen } 2394fdfb4ba6Ssthen w += sldns_str_print(s, sl, " ; "); 2395fdfb4ba6Ssthen w += sldns_wire2str_edns_option_print(s, sl, option_code, 2396fdfb4ba6Ssthen rdata, option_len); 2397fdfb4ba6Ssthen rdata += option_len; 2398fdfb4ba6Ssthen rdatalen -= option_len; 2399fdfb4ba6Ssthen } 2400fdfb4ba6Ssthen return w; 2401fdfb4ba6Ssthen } 2402fdfb4ba6Ssthen 2403fdfb4ba6Ssthen int sldns_wire2str_edns_scan(uint8_t** data, size_t* data_len, char** str, 2404fdfb4ba6Ssthen size_t* str_len, uint8_t* pkt, size_t pktlen) 2405fdfb4ba6Ssthen { 2406fdfb4ba6Ssthen int w = 0; 2407fdfb4ba6Ssthen uint8_t ext_rcode, edns_version; 2408fdfb4ba6Ssthen uint16_t udpsize, edns_bits, rdatalen; 2409fdfb4ba6Ssthen w += sldns_str_print(str, str_len, "; EDNS:"); 2410fdfb4ba6Ssthen 2411fdfb4ba6Ssthen /* some input checks, domain name */ 2412fdfb4ba6Ssthen if(*data_len < 1+10) 2413fdfb4ba6Ssthen return w + print_remainder_hex("Error malformed 0x", 2414fdfb4ba6Ssthen data, data_len, str, str_len); 2415fdfb4ba6Ssthen if(*data[0] != 0) { 2416fdfb4ba6Ssthen return w + print_remainder_hex("Error nonrootdname 0x", 2417fdfb4ba6Ssthen data, data_len, str, str_len); 2418fdfb4ba6Ssthen } 2419fdfb4ba6Ssthen (*data)++; 2420fdfb4ba6Ssthen (*data_len)--; 2421fdfb4ba6Ssthen 2422fdfb4ba6Ssthen /* check type and read fixed contents */ 2423fdfb4ba6Ssthen if(sldns_read_uint16((*data)) != LDNS_RR_TYPE_OPT) { 2424fdfb4ba6Ssthen return w + print_remainder_hex("Error nottypeOPT 0x", 2425fdfb4ba6Ssthen data, data_len, str, str_len); 2426fdfb4ba6Ssthen } 2427fdfb4ba6Ssthen udpsize = sldns_read_uint16((*data)+2); 2428fdfb4ba6Ssthen ext_rcode = (*data)[4]; 2429fdfb4ba6Ssthen edns_version = (*data)[5]; 2430fdfb4ba6Ssthen edns_bits = sldns_read_uint16((*data)+6); 2431fdfb4ba6Ssthen rdatalen = sldns_read_uint16((*data)+8); 2432fdfb4ba6Ssthen (*data)+=10; 2433fdfb4ba6Ssthen (*data_len)-=10; 2434fdfb4ba6Ssthen 2435fdfb4ba6Ssthen w += sldns_str_print(str, str_len, " version: %u;", 2436fdfb4ba6Ssthen (unsigned)edns_version); 2437fdfb4ba6Ssthen w += sldns_str_print(str, str_len, " flags:"); 2438fdfb4ba6Ssthen if((edns_bits & LDNS_EDNS_MASK_DO_BIT)) 2439fdfb4ba6Ssthen w += sldns_str_print(str, str_len, " do"); 2440fdfb4ba6Ssthen /* the extended rcode is the value set, shifted four bits, 2441fdfb4ba6Ssthen * and or'd with the original rcode */ 2442fdfb4ba6Ssthen if(ext_rcode) { 2443fdfb4ba6Ssthen int rc = ((int)ext_rcode)<<4; 2444fdfb4ba6Ssthen if(pkt && pktlen >= LDNS_HEADER_SIZE) 2445fdfb4ba6Ssthen rc |= LDNS_RCODE_WIRE(pkt); 2446fdfb4ba6Ssthen w += sldns_str_print(str, str_len, " ; ext-rcode: %d", rc); 2447fdfb4ba6Ssthen } 2448fdfb4ba6Ssthen w += sldns_str_print(str, str_len, " ; udp: %u", (unsigned)udpsize); 2449fdfb4ba6Ssthen 2450fdfb4ba6Ssthen if(rdatalen) { 245177079be7Ssthen if((size_t)*data_len < rdatalen) { 2452fdfb4ba6Ssthen w += sldns_str_print(str, str_len, 2453fdfb4ba6Ssthen " ; Error EDNS rdata too short; "); 245477079be7Ssthen rdatalen = (uint16_t)*data_len; 2455fdfb4ba6Ssthen } 2456fdfb4ba6Ssthen w += print_edns_opts(str, str_len, *data, rdatalen); 2457fdfb4ba6Ssthen (*data) += rdatalen; 2458fdfb4ba6Ssthen (*data_len) -= rdatalen; 2459fdfb4ba6Ssthen } 2460fdfb4ba6Ssthen w += sldns_str_print(str, str_len, "\n"); 2461fdfb4ba6Ssthen return w; 2462fdfb4ba6Ssthen } 2463