1ae8c6e27Sflorian /* 2ae8c6e27Sflorian * wire2str.c 3ae8c6e27Sflorian * 4ae8c6e27Sflorian * conversion routines from the wire format 5ae8c6e27Sflorian * to the presentation format (strings) 6ae8c6e27Sflorian * 7ae8c6e27Sflorian * (c) NLnet Labs, 2004-2006 8ae8c6e27Sflorian * 9ae8c6e27Sflorian * See the file LICENSE for the license 10ae8c6e27Sflorian */ 11ae8c6e27Sflorian /** 12ae8c6e27Sflorian * \file 13ae8c6e27Sflorian * 14ae8c6e27Sflorian * Contains functions to translate the wireformat to text 15ae8c6e27Sflorian * representation, as well as functions to print them. 16ae8c6e27Sflorian */ 17ae8c6e27Sflorian #include "config.h" 18ae8c6e27Sflorian #include "sldns/wire2str.h" 19ae8c6e27Sflorian #include "sldns/str2wire.h" 20ae8c6e27Sflorian #include "sldns/rrdef.h" 21ae8c6e27Sflorian #include "sldns/pkthdr.h" 22ae8c6e27Sflorian #include "sldns/parseutil.h" 23ae8c6e27Sflorian #include "sldns/sbuffer.h" 24ae8c6e27Sflorian #include "sldns/keyraw.h" 2557403691Sflorian #include "util/data/dname.h" 26ae8c6e27Sflorian #ifdef HAVE_TIME_H 27ae8c6e27Sflorian #include <time.h> 28ae8c6e27Sflorian #endif 29ae8c6e27Sflorian #include <sys/time.h> 30ae8c6e27Sflorian #include <stdarg.h> 31ae8c6e27Sflorian #include <ctype.h> 32ae8c6e27Sflorian #ifdef HAVE_NETDB_H 33ae8c6e27Sflorian #include <netdb.h> 34ae8c6e27Sflorian #endif 35ae8c6e27Sflorian 36ae8c6e27Sflorian /* lookup tables for standard DNS stuff */ 37ae8c6e27Sflorian /* Taken from RFC 2535, section 7. */ 38ae8c6e27Sflorian static sldns_lookup_table sldns_algorithms_data[] = { 39ae8c6e27Sflorian { LDNS_RSAMD5, "RSAMD5" }, 40ae8c6e27Sflorian { LDNS_DH, "DH" }, 41ae8c6e27Sflorian { LDNS_DSA, "DSA" }, 42ae8c6e27Sflorian { LDNS_ECC, "ECC" }, 43ae8c6e27Sflorian { LDNS_RSASHA1, "RSASHA1" }, 44ae8c6e27Sflorian { LDNS_DSA_NSEC3, "DSA-NSEC3-SHA1" }, 45ae8c6e27Sflorian { LDNS_RSASHA1_NSEC3, "RSASHA1-NSEC3-SHA1" }, 46ae8c6e27Sflorian { LDNS_RSASHA256, "RSASHA256"}, 47ae8c6e27Sflorian { LDNS_RSASHA512, "RSASHA512"}, 48ae8c6e27Sflorian { LDNS_ECC_GOST, "ECC-GOST"}, 49ae8c6e27Sflorian { LDNS_ECDSAP256SHA256, "ECDSAP256SHA256"}, 50ae8c6e27Sflorian { LDNS_ECDSAP384SHA384, "ECDSAP384SHA384"}, 51ae8c6e27Sflorian { LDNS_ED25519, "ED25519"}, 52ae8c6e27Sflorian { LDNS_ED448, "ED448"}, 53ae8c6e27Sflorian { LDNS_INDIRECT, "INDIRECT" }, 54ae8c6e27Sflorian { LDNS_PRIVATEDNS, "PRIVATEDNS" }, 55ae8c6e27Sflorian { LDNS_PRIVATEOID, "PRIVATEOID" }, 56ae8c6e27Sflorian { 0, NULL } 57ae8c6e27Sflorian }; 58ae8c6e27Sflorian sldns_lookup_table* sldns_algorithms = sldns_algorithms_data; 59ae8c6e27Sflorian 60ae8c6e27Sflorian /* hash algorithms in DS record */ 61ae8c6e27Sflorian static sldns_lookup_table sldns_hashes_data[] = { 62ae8c6e27Sflorian { LDNS_SHA1, "SHA1" }, 63ae8c6e27Sflorian { LDNS_SHA256, "SHA256" }, 64ae8c6e27Sflorian { LDNS_HASH_GOST, "HASH-GOST" }, 65ae8c6e27Sflorian { LDNS_SHA384, "SHA384" }, 66ae8c6e27Sflorian { 0, NULL } 67ae8c6e27Sflorian }; 68ae8c6e27Sflorian sldns_lookup_table* sldns_hashes = sldns_hashes_data; 69ae8c6e27Sflorian 70ae8c6e27Sflorian /* Taken from RFC 4398 */ 71ae8c6e27Sflorian static sldns_lookup_table sldns_cert_algorithms_data[] = { 72ae8c6e27Sflorian { LDNS_CERT_PKIX, "PKIX" }, 73ae8c6e27Sflorian { LDNS_CERT_SPKI, "SPKI" }, 74ae8c6e27Sflorian { LDNS_CERT_PGP, "PGP" }, 75ae8c6e27Sflorian { LDNS_CERT_IPKIX, "IPKIX" }, 76ae8c6e27Sflorian { LDNS_CERT_ISPKI, "ISPKI" }, 77ae8c6e27Sflorian { LDNS_CERT_IPGP, "IPGP" }, 78ae8c6e27Sflorian { LDNS_CERT_ACPKIX, "ACPKIX" }, 79ae8c6e27Sflorian { LDNS_CERT_IACPKIX, "IACPKIX" }, 80ae8c6e27Sflorian { LDNS_CERT_URI, "URI" }, 81ae8c6e27Sflorian { LDNS_CERT_OID, "OID" }, 82ae8c6e27Sflorian { 0, NULL } 83ae8c6e27Sflorian }; 84ae8c6e27Sflorian sldns_lookup_table* sldns_cert_algorithms = sldns_cert_algorithms_data; 85ae8c6e27Sflorian 86ae8c6e27Sflorian /* if these are used elsewhere */ 87ae8c6e27Sflorian static sldns_lookup_table sldns_rcodes_data[] = { 88ae8c6e27Sflorian { LDNS_RCODE_NOERROR, "NOERROR" }, 89ae8c6e27Sflorian { LDNS_RCODE_FORMERR, "FORMERR" }, 90ae8c6e27Sflorian { LDNS_RCODE_SERVFAIL, "SERVFAIL" }, 91ae8c6e27Sflorian { LDNS_RCODE_NXDOMAIN, "NXDOMAIN" }, 92ae8c6e27Sflorian { LDNS_RCODE_NOTIMPL, "NOTIMPL" }, 93ae8c6e27Sflorian { LDNS_RCODE_REFUSED, "REFUSED" }, 94ae8c6e27Sflorian { LDNS_RCODE_YXDOMAIN, "YXDOMAIN" }, 95ae8c6e27Sflorian { LDNS_RCODE_YXRRSET, "YXRRSET" }, 96ae8c6e27Sflorian { LDNS_RCODE_NXRRSET, "NXRRSET" }, 97ae8c6e27Sflorian { LDNS_RCODE_NOTAUTH, "NOTAUTH" }, 98ae8c6e27Sflorian { LDNS_RCODE_NOTZONE, "NOTZONE" }, 99ae8c6e27Sflorian { 0, NULL } 100ae8c6e27Sflorian }; 101ae8c6e27Sflorian sldns_lookup_table* sldns_rcodes = sldns_rcodes_data; 102ae8c6e27Sflorian 103ae8c6e27Sflorian static sldns_lookup_table sldns_opcodes_data[] = { 104ae8c6e27Sflorian { LDNS_PACKET_QUERY, "QUERY" }, 105ae8c6e27Sflorian { LDNS_PACKET_IQUERY, "IQUERY" }, 106ae8c6e27Sflorian { LDNS_PACKET_STATUS, "STATUS" }, 107ae8c6e27Sflorian { LDNS_PACKET_NOTIFY, "NOTIFY" }, 108ae8c6e27Sflorian { LDNS_PACKET_UPDATE, "UPDATE" }, 109ae8c6e27Sflorian { 0, NULL } 110ae8c6e27Sflorian }; 111ae8c6e27Sflorian sldns_lookup_table* sldns_opcodes = sldns_opcodes_data; 112ae8c6e27Sflorian 113ae8c6e27Sflorian static sldns_lookup_table sldns_wireparse_errors_data[] = { 114ae8c6e27Sflorian { LDNS_WIREPARSE_ERR_OK, "no parse error" }, 115ae8c6e27Sflorian { LDNS_WIREPARSE_ERR_GENERAL, "parse error" }, 116ae8c6e27Sflorian { LDNS_WIREPARSE_ERR_DOMAINNAME_OVERFLOW, "Domainname length overflow" }, 117ae8c6e27Sflorian { LDNS_WIREPARSE_ERR_DOMAINNAME_UNDERFLOW, "Domainname length underflow (zero length)" }, 118ae8c6e27Sflorian { LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, "buffer too small" }, 119ae8c6e27Sflorian { LDNS_WIREPARSE_ERR_LABEL_OVERFLOW, "Label length overflow" }, 120ae8c6e27Sflorian { LDNS_WIREPARSE_ERR_EMPTY_LABEL, "Empty label" }, 121ae8c6e27Sflorian { LDNS_WIREPARSE_ERR_SYNTAX_BAD_ESCAPE, "Syntax error, bad escape sequence" }, 122ae8c6e27Sflorian { LDNS_WIREPARSE_ERR_SYNTAX, "Syntax error, could not parse the RR" }, 123ae8c6e27Sflorian { LDNS_WIREPARSE_ERR_SYNTAX_TTL, "Syntax error, could not parse the RR's TTL" }, 124ae8c6e27Sflorian { LDNS_WIREPARSE_ERR_SYNTAX_TYPE, "Syntax error, could not parse the RR's type" }, 125ae8c6e27Sflorian { LDNS_WIREPARSE_ERR_SYNTAX_CLASS, "Syntax error, could not parse the RR's class" }, 126ae8c6e27Sflorian { LDNS_WIREPARSE_ERR_SYNTAX_RDATA, "Syntax error, could not parse the RR's rdata" }, 127ae8c6e27Sflorian { LDNS_WIREPARSE_ERR_SYNTAX_MISSING_VALUE, "Syntax error, value expected" }, 128ae8c6e27Sflorian { LDNS_WIREPARSE_ERR_INVALID_STR, "Conversion error, string expected" }, 129ae8c6e27Sflorian { LDNS_WIREPARSE_ERR_SYNTAX_B64, "Conversion error, b64 encoding expected" }, 130ae8c6e27Sflorian { LDNS_WIREPARSE_ERR_SYNTAX_B32_EXT, "Conversion error, b32 ext encoding expected" }, 131ae8c6e27Sflorian { LDNS_WIREPARSE_ERR_SYNTAX_HEX, "Conversion error, hex encoding expected" }, 132ae8c6e27Sflorian { LDNS_WIREPARSE_ERR_CERT_BAD_ALGORITHM, "Bad algorithm type for CERT record" }, 133ae8c6e27Sflorian { LDNS_WIREPARSE_ERR_SYNTAX_TIME, "Conversion error, time encoding expected" }, 134ae8c6e27Sflorian { LDNS_WIREPARSE_ERR_SYNTAX_PERIOD, "Conversion error, time period encoding expected" }, 135ae8c6e27Sflorian { LDNS_WIREPARSE_ERR_SYNTAX_ILNP64, "Conversion error, 4 colon separated hex numbers expected" }, 136ae8c6e27Sflorian { LDNS_WIREPARSE_ERR_SYNTAX_EUI48, 137ae8c6e27Sflorian "Conversion error, 6 two character hex numbers " 138ae8c6e27Sflorian "separated by dashes expected (i.e. xx-xx-xx-xx-xx-xx" }, 139ae8c6e27Sflorian { LDNS_WIREPARSE_ERR_SYNTAX_EUI64, 140ae8c6e27Sflorian "Conversion error, 8 two character hex numbers " 141ae8c6e27Sflorian "separated by dashes expected (i.e. xx-xx-xx-xx-xx-xx-xx-xx" }, 142ae8c6e27Sflorian { LDNS_WIREPARSE_ERR_SYNTAX_TAG, 143ae8c6e27Sflorian "Conversion error, a non-zero sequence of US-ASCII letters " 144ae8c6e27Sflorian "and numbers in lower case expected" }, 145ae8c6e27Sflorian { LDNS_WIREPARSE_ERR_NOT_IMPL, "not implemented" }, 146ae8c6e27Sflorian { LDNS_WIREPARSE_ERR_SYNTAX_INT, "Conversion error, integer expected" }, 147ae8c6e27Sflorian { LDNS_WIREPARSE_ERR_SYNTAX_IP4, "Conversion error, ip4 addr expected" }, 148ae8c6e27Sflorian { LDNS_WIREPARSE_ERR_SYNTAX_IP6, "Conversion error, ip6 addr expected" }, 149ae8c6e27Sflorian { LDNS_WIREPARSE_ERR_SYNTAX_INTEGER_OVERFLOW, "Syntax error, integer overflow" }, 150ae8c6e27Sflorian { LDNS_WIREPARSE_ERR_INCLUDE, "$INCLUDE directive was seen in the zone" }, 151ae8c6e27Sflorian { LDNS_WIREPARSE_ERR_PARENTHESIS, "Parse error, parenthesis mismatch" }, 152411c5950Sflorian { LDNS_WIREPARSE_ERR_SVCB_UNKNOWN_KEY, "Unknown SvcParamKey"}, 153411c5950Sflorian { LDNS_WIREPARSE_ERR_SVCB_MISSING_PARAM, "SvcParam is missing a SvcParamValue"}, 154411c5950Sflorian { LDNS_WIREPARSE_ERR_SVCB_DUPLICATE_KEYS, "Duplicate SVCB key found"}, 155411c5950Sflorian { LDNS_WIREPARSE_ERR_SVCB_MANDATORY_TOO_MANY_KEYS, "Too many keys in mandatory" }, 156411c5950Sflorian { LDNS_WIREPARSE_ERR_SVCB_TOO_MANY_PARAMS, 157411c5950Sflorian "Too many SvcParams. Unbound only allows 63 entries" }, 158411c5950Sflorian { LDNS_WIREPARSE_ERR_SVCB_MANDATORY_MISSING_PARAM, 159411c5950Sflorian "Mandatory SvcParamKey is missing"}, 160411c5950Sflorian { LDNS_WIREPARSE_ERR_SVCB_MANDATORY_DUPLICATE_KEY, 161411c5950Sflorian "Keys in SvcParam mandatory MUST be unique" }, 162411c5950Sflorian { LDNS_WIREPARSE_ERR_SVCB_MANDATORY_IN_MANDATORY, 163411c5950Sflorian "mandatory MUST not be included as mandatory parameter" }, 164411c5950Sflorian { LDNS_WIREPARSE_ERR_SVCB_PORT_VALUE_SYNTAX, 165411c5950Sflorian "Could not parse port SvcParamValue" }, 166411c5950Sflorian { LDNS_WIREPARSE_ERR_SVCB_IPV4_TOO_MANY_ADDRESSES, 167411c5950Sflorian "Too many IPv4 addresses in ipv4hint" }, 168411c5950Sflorian { LDNS_WIREPARSE_ERR_SVCB_IPV6_TOO_MANY_ADDRESSES, 169411c5950Sflorian "Too many IPv6 addresses in ipv6hint" }, 170411c5950Sflorian { LDNS_WIREPARSE_ERR_SVCB_ALPN_KEY_TOO_LARGE, 171411c5950Sflorian "Alpn strings need to be smaller than 255 chars"}, 172411c5950Sflorian { LDNS_WIREPARSE_ERR_SVCB_NO_DEFAULT_ALPN_VALUE, 173411c5950Sflorian "No-default-alpn should not have a value" }, 174411c5950Sflorian { LDNS_WIREPARSE_ERR_SVCPARAM_BROKEN_RDATA, 175411c5950Sflorian "General SVCParam error" }, 176ae8c6e27Sflorian { 0, NULL } 177ae8c6e27Sflorian }; 178ae8c6e27Sflorian sldns_lookup_table* sldns_wireparse_errors = sldns_wireparse_errors_data; 179ae8c6e27Sflorian 180ae8c6e27Sflorian static sldns_lookup_table sldns_edns_flags_data[] = { 181ae8c6e27Sflorian { 3600, "do"}, 182ae8c6e27Sflorian { 0, NULL} 183ae8c6e27Sflorian }; 184ae8c6e27Sflorian sldns_lookup_table* sldns_edns_flags = sldns_edns_flags_data; 185ae8c6e27Sflorian 186ae8c6e27Sflorian static sldns_lookup_table sldns_edns_options_data[] = { 187ae8c6e27Sflorian { 1, "LLQ" }, 188ae8c6e27Sflorian { 2, "UL" }, 189ae8c6e27Sflorian { 3, "NSID" }, 190ae8c6e27Sflorian /* 4 draft-cheshire-edns0-owner-option */ 191ae8c6e27Sflorian { 5, "DAU" }, 192ae8c6e27Sflorian { 6, "DHU" }, 193ae8c6e27Sflorian { 7, "N3U" }, 194ae8c6e27Sflorian { 8, "edns-client-subnet" }, 19554cc57acSflorian { 10, "COOKIE" }, 196ae8c6e27Sflorian { 11, "edns-tcp-keepalive"}, 197ae8c6e27Sflorian { 12, "Padding" }, 1987a05b9dfSflorian { 15, "EDE"}, 199ae8c6e27Sflorian { 0, NULL} 200ae8c6e27Sflorian }; 201ae8c6e27Sflorian sldns_lookup_table* sldns_edns_options = sldns_edns_options_data; 202ae8c6e27Sflorian 20354cc57acSflorian /* From RFC8914 5.2 Table 3, the "Extended DNS Error Codes" registry. */ 20454cc57acSflorian static sldns_lookup_table sldns_edns_ede_codes_data[] = { 20554cc57acSflorian { LDNS_EDE_NONE, "None" }, 20654cc57acSflorian { LDNS_EDE_OTHER, "Other Error" }, 20754cc57acSflorian { LDNS_EDE_UNSUPPORTED_DNSKEY_ALG, "Unsupported DNSKEY Algorithm" }, 20854cc57acSflorian { LDNS_EDE_UNSUPPORTED_DS_DIGEST, "Unsupported DS Digest Type" }, 20954cc57acSflorian { LDNS_EDE_STALE_ANSWER, "Stale Answer" }, 21054cc57acSflorian { LDNS_EDE_FORGED_ANSWER, "Forged Answer" }, 21154cc57acSflorian { LDNS_EDE_DNSSEC_INDETERMINATE, "DNSSEC Indeterminate" }, 21254cc57acSflorian { LDNS_EDE_DNSSEC_BOGUS, "DNSSEC Bogus" }, 21354cc57acSflorian { LDNS_EDE_SIGNATURE_EXPIRED, "Signature Expired" }, 21454cc57acSflorian { LDNS_EDE_SIGNATURE_NOT_YET_VALID, "Signature Not Yet Valid" }, 21554cc57acSflorian { LDNS_EDE_DNSKEY_MISSING, "DNSKEY Missing" }, 21654cc57acSflorian { LDNS_EDE_RRSIGS_MISSING, "RRSIGs Missing" }, 21754cc57acSflorian { LDNS_EDE_NO_ZONE_KEY_BIT_SET, "No Zone Key Bit Set" }, 21854cc57acSflorian { LDNS_EDE_NSEC_MISSING, "NSEC Missing" }, 21954cc57acSflorian { LDNS_EDE_CACHED_ERROR, "Cached Error" }, 22054cc57acSflorian { LDNS_EDE_NOT_READY, "Not Ready" }, 22154cc57acSflorian { LDNS_EDE_BLOCKED, "Blocked" }, 22254cc57acSflorian { LDNS_EDE_CENSORED, "Censored" }, 22354cc57acSflorian { LDNS_EDE_FILTERED, "Filtered" }, 22454cc57acSflorian { LDNS_EDE_PROHIBITED, "Prohibited" }, 22554cc57acSflorian { LDNS_EDE_STALE_NXDOMAIN_ANSWER, "Stale NXDOMAIN Answer" }, 22654cc57acSflorian { LDNS_EDE_NOT_AUTHORITATIVE, "Not Authoritative" }, 22754cc57acSflorian { LDNS_EDE_NOT_SUPPORTED, "Not Supported" }, 22854cc57acSflorian { LDNS_EDE_NO_REACHABLE_AUTHORITY, "No Reachable Authority" }, 22954cc57acSflorian { LDNS_EDE_NETWORK_ERROR, "Network Error" }, 23054cc57acSflorian { LDNS_EDE_INVALID_DATA, "Invalid Data" }, 231*7037e34cSflorian { LDNS_EDE_SIGNATURE_EXPIRED_BEFORE_VALID, "Signature Expired Before Valid" }, 232*7037e34cSflorian { LDNS_EDE_TOO_EARLY, "Non-Replayable Transactions Received in 0-RTT Data" }, 233*7037e34cSflorian { LDNS_EDE_UNSUPPORTED_NSEC3_ITERATIONS, "Unsupported NSEC3 Iterations Value" }, 234*7037e34cSflorian { LDNS_EDE_BADPROXYPOLICY, "Unable to Conform to Policy" }, 235*7037e34cSflorian { LDNS_EDE_SYNTHESIZED, "Synthesized Answer" }, 23654cc57acSflorian { 0, NULL} 23754cc57acSflorian }; 23854cc57acSflorian sldns_lookup_table* sldns_edns_ede_codes = sldns_edns_ede_codes_data; 23954cc57acSflorian 240ae8c6e27Sflorian static sldns_lookup_table sldns_tsig_errors_data[] = { 241ae8c6e27Sflorian { LDNS_TSIG_ERROR_NOERROR, "NOERROR" }, 242ae8c6e27Sflorian { LDNS_RCODE_FORMERR, "FORMERR" }, 243ae8c6e27Sflorian { LDNS_RCODE_SERVFAIL, "SERVFAIL" }, 244ae8c6e27Sflorian { LDNS_RCODE_NXDOMAIN, "NXDOMAIN" }, 245ae8c6e27Sflorian { LDNS_RCODE_NOTIMPL, "NOTIMPL" }, 246ae8c6e27Sflorian { LDNS_RCODE_REFUSED, "REFUSED" }, 247ae8c6e27Sflorian { LDNS_RCODE_YXDOMAIN, "YXDOMAIN" }, 248ae8c6e27Sflorian { LDNS_RCODE_YXRRSET, "YXRRSET" }, 249ae8c6e27Sflorian { LDNS_RCODE_NXRRSET, "NXRRSET" }, 250ae8c6e27Sflorian { LDNS_RCODE_NOTAUTH, "NOTAUTH" }, 251ae8c6e27Sflorian { LDNS_RCODE_NOTZONE, "NOTZONE" }, 252ae8c6e27Sflorian { LDNS_TSIG_ERROR_BADSIG, "BADSIG" }, 253ae8c6e27Sflorian { LDNS_TSIG_ERROR_BADKEY, "BADKEY" }, 254ae8c6e27Sflorian { LDNS_TSIG_ERROR_BADTIME, "BADTIME" }, 255ae8c6e27Sflorian { LDNS_TSIG_ERROR_BADMODE, "BADMODE" }, 256ae8c6e27Sflorian { LDNS_TSIG_ERROR_BADNAME, "BADNAME" }, 257ae8c6e27Sflorian { LDNS_TSIG_ERROR_BADALG, "BADALG" }, 258ae8c6e27Sflorian { 0, NULL } 259ae8c6e27Sflorian }; 260ae8c6e27Sflorian sldns_lookup_table* sldns_tsig_errors = sldns_tsig_errors_data; 261ae8c6e27Sflorian 262411c5950Sflorian /* draft-ietf-dnsop-svcb-https-06: 6. Initial SvcParamKeys */ 263411c5950Sflorian const char *svcparamkey_strs[] = { 264411c5950Sflorian "mandatory", "alpn", "no-default-alpn", "port", 265d500c338Sflorian "ipv4hint", "ech", "ipv6hint", "dohpath" 266411c5950Sflorian }; 267411c5950Sflorian 268ae8c6e27Sflorian char* sldns_wire2str_pkt(uint8_t* data, size_t len) 269ae8c6e27Sflorian { 270ae8c6e27Sflorian size_t slen = (size_t)sldns_wire2str_pkt_buf(data, len, NULL, 0); 271ae8c6e27Sflorian char* result = (char*)malloc(slen+1); 272ae8c6e27Sflorian if(!result) return NULL; 273ae8c6e27Sflorian sldns_wire2str_pkt_buf(data, len, result, slen+1); 274ae8c6e27Sflorian return result; 275ae8c6e27Sflorian } 276ae8c6e27Sflorian 277ae8c6e27Sflorian char* sldns_wire2str_rr(uint8_t* rr, size_t len) 278ae8c6e27Sflorian { 279ae8c6e27Sflorian size_t slen = (size_t)sldns_wire2str_rr_buf(rr, len, NULL, 0); 280ae8c6e27Sflorian char* result = (char*)malloc(slen+1); 281ae8c6e27Sflorian if(!result) return NULL; 282ae8c6e27Sflorian sldns_wire2str_rr_buf(rr, len, result, slen+1); 283ae8c6e27Sflorian return result; 284ae8c6e27Sflorian } 285ae8c6e27Sflorian 286ae8c6e27Sflorian char* sldns_wire2str_type(uint16_t rrtype) 287ae8c6e27Sflorian { 288ae8c6e27Sflorian char buf[16]; 289ae8c6e27Sflorian sldns_wire2str_type_buf(rrtype, buf, sizeof(buf)); 290ae8c6e27Sflorian return strdup(buf); 291ae8c6e27Sflorian } 292ae8c6e27Sflorian 293ae8c6e27Sflorian char* sldns_wire2str_class(uint16_t rrclass) 294ae8c6e27Sflorian { 295ae8c6e27Sflorian char buf[16]; 296ae8c6e27Sflorian sldns_wire2str_class_buf(rrclass, buf, sizeof(buf)); 297ae8c6e27Sflorian return strdup(buf); 298ae8c6e27Sflorian } 299ae8c6e27Sflorian 300ae8c6e27Sflorian char* sldns_wire2str_dname(uint8_t* dname, size_t dname_len) 301ae8c6e27Sflorian { 302ae8c6e27Sflorian size_t slen=(size_t)sldns_wire2str_dname_buf(dname, dname_len, NULL, 0); 303ae8c6e27Sflorian char* result = (char*)malloc(slen+1); 304ae8c6e27Sflorian if(!result) return NULL; 305ae8c6e27Sflorian sldns_wire2str_dname_buf(dname, dname_len, result, slen+1); 306ae8c6e27Sflorian return result; 307ae8c6e27Sflorian } 308ae8c6e27Sflorian 309ae8c6e27Sflorian char* sldns_wire2str_rcode(int rcode) 310ae8c6e27Sflorian { 311ae8c6e27Sflorian char buf[16]; 312ae8c6e27Sflorian sldns_wire2str_rcode_buf(rcode, buf, sizeof(buf)); 313ae8c6e27Sflorian return strdup(buf); 314ae8c6e27Sflorian } 315ae8c6e27Sflorian 316ae8c6e27Sflorian int sldns_wire2str_pkt_buf(uint8_t* d, size_t dlen, char* s, size_t slen) 317ae8c6e27Sflorian { 318ae8c6e27Sflorian /* use arguments as temporary variables */ 319ae8c6e27Sflorian return sldns_wire2str_pkt_scan(&d, &dlen, &s, &slen); 320ae8c6e27Sflorian } 321ae8c6e27Sflorian 322ae8c6e27Sflorian int sldns_wire2str_rr_buf(uint8_t* d, size_t dlen, char* s, size_t slen) 323ae8c6e27Sflorian { 324ae8c6e27Sflorian /* use arguments as temporary variables */ 32557403691Sflorian return sldns_wire2str_rr_scan(&d, &dlen, &s, &slen, NULL, 0, NULL); 326ae8c6e27Sflorian } 327ae8c6e27Sflorian 328ae8c6e27Sflorian int sldns_wire2str_rrquestion_buf(uint8_t* d, size_t dlen, char* s, size_t slen) 329ae8c6e27Sflorian { 330ae8c6e27Sflorian /* use arguments as temporary variables */ 33157403691Sflorian return sldns_wire2str_rrquestion_scan(&d, &dlen, &s, &slen, NULL, 0, NULL); 332ae8c6e27Sflorian } 333ae8c6e27Sflorian 334ae8c6e27Sflorian int sldns_wire2str_rdata_buf(uint8_t* rdata, size_t rdata_len, char* str, 335ae8c6e27Sflorian size_t str_len, uint16_t rrtype) 336ae8c6e27Sflorian { 337ae8c6e27Sflorian /* use arguments as temporary variables */ 338ae8c6e27Sflorian return sldns_wire2str_rdata_scan(&rdata, &rdata_len, &str, &str_len, 33957403691Sflorian rrtype, NULL, 0, NULL); 340ae8c6e27Sflorian } 341ae8c6e27Sflorian 342ae8c6e27Sflorian int sldns_wire2str_rr_unknown_buf(uint8_t* d, size_t dlen, char* s, size_t slen) 343ae8c6e27Sflorian { 344ae8c6e27Sflorian /* use arguments as temporary variables */ 34557403691Sflorian return sldns_wire2str_rr_unknown_scan(&d, &dlen, &s, &slen, NULL, 0, NULL); 346ae8c6e27Sflorian } 347ae8c6e27Sflorian 348ae8c6e27Sflorian int sldns_wire2str_rr_comment_buf(uint8_t* rr, size_t rrlen, size_t dname_len, 349ae8c6e27Sflorian char* s, size_t slen) 350ae8c6e27Sflorian { 351ae8c6e27Sflorian uint16_t rrtype = sldns_wirerr_get_type(rr, rrlen, dname_len); 352ae8c6e27Sflorian return sldns_wire2str_rr_comment_print(&s, &slen, rr, rrlen, dname_len, 353ae8c6e27Sflorian rrtype); 354ae8c6e27Sflorian } 355ae8c6e27Sflorian 356ae8c6e27Sflorian int sldns_wire2str_type_buf(uint16_t rrtype, char* s, size_t slen) 357ae8c6e27Sflorian { 358ae8c6e27Sflorian /* use arguments as temporary variables */ 359ae8c6e27Sflorian return sldns_wire2str_type_print(&s, &slen, rrtype); 360ae8c6e27Sflorian } 361ae8c6e27Sflorian 362ae8c6e27Sflorian int sldns_wire2str_class_buf(uint16_t rrclass, char* s, size_t slen) 363ae8c6e27Sflorian { 364ae8c6e27Sflorian /* use arguments as temporary variables */ 365ae8c6e27Sflorian return sldns_wire2str_class_print(&s, &slen, rrclass); 366ae8c6e27Sflorian } 367ae8c6e27Sflorian 368ae8c6e27Sflorian int sldns_wire2str_rcode_buf(int rcode, char* s, size_t slen) 369ae8c6e27Sflorian { 370ae8c6e27Sflorian /* use arguments as temporary variables */ 371ae8c6e27Sflorian return sldns_wire2str_rcode_print(&s, &slen, rcode); 372ae8c6e27Sflorian } 373ae8c6e27Sflorian 374ae8c6e27Sflorian int sldns_wire2str_opcode_buf(int opcode, char* s, size_t slen) 375ae8c6e27Sflorian { 376ae8c6e27Sflorian /* use arguments as temporary variables */ 377ae8c6e27Sflorian return sldns_wire2str_opcode_print(&s, &slen, opcode); 378ae8c6e27Sflorian } 379ae8c6e27Sflorian 380ae8c6e27Sflorian int sldns_wire2str_dname_buf(uint8_t* d, size_t dlen, char* s, size_t slen) 381ae8c6e27Sflorian { 382ae8c6e27Sflorian /* use arguments as temporary variables */ 38357403691Sflorian return sldns_wire2str_dname_scan(&d, &dlen, &s, &slen, NULL, 0, NULL); 384ae8c6e27Sflorian } 385ae8c6e27Sflorian 386ae8c6e27Sflorian int sldns_str_vprint(char** str, size_t* slen, const char* format, va_list args) 387ae8c6e27Sflorian { 388ae8c6e27Sflorian int w = vsnprintf(*str, *slen, format, args); 389ae8c6e27Sflorian if(w < 0) { 390ae8c6e27Sflorian /* error in printout */ 391ae8c6e27Sflorian return 0; 392ae8c6e27Sflorian } else if((size_t)w >= *slen) { 393ae8c6e27Sflorian *str = NULL; /* we do not want str to point outside of buffer*/ 394ae8c6e27Sflorian *slen = 0; 395ae8c6e27Sflorian } else { 396ae8c6e27Sflorian *str += w; 397ae8c6e27Sflorian *slen -= w; 398ae8c6e27Sflorian } 399ae8c6e27Sflorian return w; 400ae8c6e27Sflorian } 401ae8c6e27Sflorian 402ae8c6e27Sflorian int sldns_str_print(char** str, size_t* slen, const char* format, ...) 403ae8c6e27Sflorian { 404ae8c6e27Sflorian int w; 405ae8c6e27Sflorian va_list args; 406ae8c6e27Sflorian va_start(args, format); 407ae8c6e27Sflorian w = sldns_str_vprint(str, slen, format, args); 408ae8c6e27Sflorian va_end(args); 409ae8c6e27Sflorian return w; 410ae8c6e27Sflorian } 411ae8c6e27Sflorian 412ae8c6e27Sflorian /** print hex format into text buffer for specified length */ 413ae8c6e27Sflorian static int print_hex_buf(char** s, size_t* slen, uint8_t* buf, size_t len) 414ae8c6e27Sflorian { 415ae8c6e27Sflorian const char* hex = "0123456789ABCDEF"; 416ae8c6e27Sflorian size_t i; 417ae8c6e27Sflorian for(i=0; i<len; i++) { 418ae8c6e27Sflorian (void)sldns_str_print(s, slen, "%c%c", hex[(buf[i]&0xf0)>>4], 419ae8c6e27Sflorian hex[buf[i]&0x0f]); 420ae8c6e27Sflorian } 421ae8c6e27Sflorian return (int)len*2; 422ae8c6e27Sflorian } 423ae8c6e27Sflorian 424ae8c6e27Sflorian /** print remainder of buffer in hex format with prefixed text */ 425ae8c6e27Sflorian static int print_remainder_hex(const char* pref, uint8_t** d, size_t* dlen, 426ae8c6e27Sflorian char** s, size_t* slen) 427ae8c6e27Sflorian { 428ae8c6e27Sflorian int w = 0; 429ae8c6e27Sflorian w += sldns_str_print(s, slen, "%s", pref); 430ae8c6e27Sflorian w += print_hex_buf(s, slen, *d, *dlen); 431ae8c6e27Sflorian *d += *dlen; 432ae8c6e27Sflorian *dlen = 0; 433ae8c6e27Sflorian return w; 434ae8c6e27Sflorian } 435ae8c6e27Sflorian 436ae8c6e27Sflorian int sldns_wire2str_pkt_scan(uint8_t** d, size_t* dlen, char** s, size_t* slen) 437ae8c6e27Sflorian { 43857403691Sflorian int w = 0, comprloop = 0; 439ae8c6e27Sflorian unsigned qdcount, ancount, nscount, arcount, i; 440ae8c6e27Sflorian uint8_t* pkt = *d; 441ae8c6e27Sflorian size_t pktlen = *dlen; 442ae8c6e27Sflorian if(*dlen >= LDNS_HEADER_SIZE) { 443ae8c6e27Sflorian qdcount = (unsigned)LDNS_QDCOUNT(*d); 444ae8c6e27Sflorian ancount = (unsigned)LDNS_ANCOUNT(*d); 445ae8c6e27Sflorian nscount = (unsigned)LDNS_NSCOUNT(*d); 446ae8c6e27Sflorian arcount = (unsigned)LDNS_ARCOUNT(*d); 447ae8c6e27Sflorian } else { 448ae8c6e27Sflorian qdcount = ancount = nscount = arcount = 0; 449ae8c6e27Sflorian } 450ae8c6e27Sflorian w += sldns_wire2str_header_scan(d, dlen, s, slen); 451ae8c6e27Sflorian w += sldns_str_print(s, slen, "\n"); 452ae8c6e27Sflorian w += sldns_str_print(s, slen, ";; QUESTION SECTION:\n"); 453ae8c6e27Sflorian for(i=0; i<qdcount; i++) { 454ae8c6e27Sflorian w += sldns_wire2str_rrquestion_scan(d, dlen, s, slen, 45557403691Sflorian pkt, pktlen, &comprloop); 456ae8c6e27Sflorian if(!*dlen) break; 457ae8c6e27Sflorian } 458ae8c6e27Sflorian w += sldns_str_print(s, slen, "\n"); 459ae8c6e27Sflorian w += sldns_str_print(s, slen, ";; ANSWER SECTION:\n"); 460ae8c6e27Sflorian for(i=0; i<ancount; i++) { 46157403691Sflorian w += sldns_wire2str_rr_scan(d, dlen, s, slen, pkt, pktlen, &comprloop); 462ae8c6e27Sflorian if(!*dlen) break; 463ae8c6e27Sflorian } 464ae8c6e27Sflorian w += sldns_str_print(s, slen, "\n"); 465ae8c6e27Sflorian w += sldns_str_print(s, slen, ";; AUTHORITY SECTION:\n"); 466ae8c6e27Sflorian for(i=0; i<nscount; i++) { 46757403691Sflorian w += sldns_wire2str_rr_scan(d, dlen, s, slen, pkt, pktlen, &comprloop); 468ae8c6e27Sflorian if(!*dlen) break; 469ae8c6e27Sflorian } 470ae8c6e27Sflorian w += sldns_str_print(s, slen, "\n"); 471ae8c6e27Sflorian w += sldns_str_print(s, slen, ";; ADDITIONAL SECTION:\n"); 472ae8c6e27Sflorian for(i=0; i<arcount; i++) { 47357403691Sflorian w += sldns_wire2str_rr_scan(d, dlen, s, slen, pkt, pktlen, &comprloop); 474ae8c6e27Sflorian if(!*dlen) break; 475ae8c6e27Sflorian } 476ae8c6e27Sflorian /* other fields: WHEN(time), SERVER(IP) not available here. */ 477ae8c6e27Sflorian w += sldns_str_print(s, slen, ";; MSG SIZE rcvd: %d\n", (int)pktlen); 478ae8c6e27Sflorian if(*dlen > 0) { 479ae8c6e27Sflorian w += print_remainder_hex(";; trailing garbage 0x", 480ae8c6e27Sflorian d, dlen, s, slen); 481ae8c6e27Sflorian w += sldns_str_print(s, slen, "\n"); 482ae8c6e27Sflorian } 483ae8c6e27Sflorian return w; 484ae8c6e27Sflorian } 485ae8c6e27Sflorian 486ae8c6e27Sflorian /** scan type, class and ttl and printout, for rr */ 487ae8c6e27Sflorian static int sldns_rr_tcttl_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) 488ae8c6e27Sflorian { 489ae8c6e27Sflorian int w = 0; 490ae8c6e27Sflorian uint16_t t, c; 491ae8c6e27Sflorian uint32_t ttl; 492ae8c6e27Sflorian if(*dl < 8) { 493ae8c6e27Sflorian if(*dl < 4) 494ae8c6e27Sflorian return w + print_remainder_hex("; Error malformed 0x", 495ae8c6e27Sflorian d, dl, s, sl); 496ae8c6e27Sflorian /* these print values or 0x.. if none left */ 497ae8c6e27Sflorian t = sldns_read_uint16(*d); 498ae8c6e27Sflorian c = sldns_read_uint16((*d)+2); 499ae8c6e27Sflorian (*d)+=4; 500ae8c6e27Sflorian (*dl)-=4; 501ae8c6e27Sflorian w += sldns_wire2str_class_print(s, sl, c); 502ae8c6e27Sflorian w += sldns_str_print(s, sl, "\t"); 503ae8c6e27Sflorian w += sldns_wire2str_type_print(s, sl, t); 504ae8c6e27Sflorian if(*dl == 0) 505ae8c6e27Sflorian return w + sldns_str_print(s, sl, "; Error no ttl"); 506ae8c6e27Sflorian return w + print_remainder_hex( 507ae8c6e27Sflorian "; Error malformed ttl 0x", d, dl, s, sl); 508ae8c6e27Sflorian } 509ae8c6e27Sflorian t = sldns_read_uint16(*d); 510ae8c6e27Sflorian c = sldns_read_uint16((*d)+2); 511ae8c6e27Sflorian ttl = sldns_read_uint32((*d)+4); 512ae8c6e27Sflorian (*d)+=8; 513ae8c6e27Sflorian (*dl)-=8; 514ae8c6e27Sflorian w += sldns_str_print(s, sl, "%lu\t", (unsigned long)ttl); 515ae8c6e27Sflorian w += sldns_wire2str_class_print(s, sl, c); 516ae8c6e27Sflorian w += sldns_str_print(s, sl, "\t"); 517ae8c6e27Sflorian w += sldns_wire2str_type_print(s, sl, t); 518ae8c6e27Sflorian return w; 519ae8c6e27Sflorian } 520ae8c6e27Sflorian 521ae8c6e27Sflorian int sldns_wire2str_rr_scan(uint8_t** d, size_t* dlen, char** s, size_t* slen, 52257403691Sflorian uint8_t* pkt, size_t pktlen, int* comprloop) 523ae8c6e27Sflorian { 524ae8c6e27Sflorian int w = 0; 525ae8c6e27Sflorian uint8_t* rr = *d; 526ae8c6e27Sflorian size_t rrlen = *dlen, dname_off, rdlen, ordlen; 527ae8c6e27Sflorian uint16_t rrtype = 0; 528ae8c6e27Sflorian 529ae8c6e27Sflorian if(*dlen >= 3 && (*d)[0]==0 && 530ae8c6e27Sflorian sldns_read_uint16((*d)+1)==LDNS_RR_TYPE_OPT) { 531ae8c6e27Sflorian /* perform EDNS OPT processing */ 532ae8c6e27Sflorian return sldns_wire2str_edns_scan(d, dlen, s, slen, pkt, pktlen); 533ae8c6e27Sflorian } 534ae8c6e27Sflorian 535ae8c6e27Sflorian /* try to scan the rdata with pretty-printing, but if that fails, then 536ae8c6e27Sflorian * scan the rdata as an unknown RR type */ 53757403691Sflorian w += sldns_wire2str_dname_scan(d, dlen, s, slen, pkt, pktlen, comprloop); 538ae8c6e27Sflorian w += sldns_str_print(s, slen, "\t"); 539ae8c6e27Sflorian dname_off = rrlen-(*dlen); 540ae8c6e27Sflorian if(*dlen == 4) { 541ae8c6e27Sflorian /* like a question-RR */ 542ae8c6e27Sflorian uint16_t t = sldns_read_uint16(*d); 543ae8c6e27Sflorian uint16_t c = sldns_read_uint16((*d)+2); 544ae8c6e27Sflorian (*d)+=4; 545ae8c6e27Sflorian (*dlen)-=4; 546ae8c6e27Sflorian w += sldns_wire2str_class_print(s, slen, c); 547ae8c6e27Sflorian w += sldns_str_print(s, slen, "\t"); 548ae8c6e27Sflorian w += sldns_wire2str_type_print(s, slen, t); 549ae8c6e27Sflorian w += sldns_str_print(s, slen, " ; Error no ttl,rdata\n"); 550ae8c6e27Sflorian return w; 551ae8c6e27Sflorian } 552ae8c6e27Sflorian if(*dlen < 8) { 553ae8c6e27Sflorian if(*dlen == 0) 554ae8c6e27Sflorian return w + sldns_str_print(s, slen, ";Error missing RR\n"); 555ae8c6e27Sflorian w += print_remainder_hex(";Error partial RR 0x", d, dlen, s, slen); 556ae8c6e27Sflorian return w + sldns_str_print(s, slen, "\n"); 557ae8c6e27Sflorian } 558ae8c6e27Sflorian rrtype = sldns_read_uint16(*d); 559ae8c6e27Sflorian w += sldns_rr_tcttl_scan(d, dlen, s, slen); 560ae8c6e27Sflorian w += sldns_str_print(s, slen, "\t"); 561ae8c6e27Sflorian 562ae8c6e27Sflorian /* rdata */ 563ae8c6e27Sflorian if(*dlen < 2) { 564ae8c6e27Sflorian if(*dlen == 0) 565ae8c6e27Sflorian return w + sldns_str_print(s, slen, ";Error missing rdatalen\n"); 566ae8c6e27Sflorian w += print_remainder_hex(";Error missing rdatalen 0x", 567ae8c6e27Sflorian d, dlen, s, slen); 568ae8c6e27Sflorian return w + sldns_str_print(s, slen, "\n"); 569ae8c6e27Sflorian } 570ae8c6e27Sflorian rdlen = sldns_read_uint16(*d); 571ae8c6e27Sflorian ordlen = rdlen; 572ae8c6e27Sflorian (*d)+=2; 573ae8c6e27Sflorian (*dlen)-=2; 574ae8c6e27Sflorian if(*dlen < rdlen) { 575ae8c6e27Sflorian w += sldns_str_print(s, slen, "\\# %u ", (unsigned)rdlen); 576ae8c6e27Sflorian if(*dlen == 0) 577ae8c6e27Sflorian return w + sldns_str_print(s, slen, ";Error missing rdata\n"); 578ae8c6e27Sflorian w += print_remainder_hex(";Error partial rdata 0x", d, dlen, s, slen); 579ae8c6e27Sflorian return w + sldns_str_print(s, slen, "\n"); 580ae8c6e27Sflorian } 58157403691Sflorian w += sldns_wire2str_rdata_scan(d, &rdlen, s, slen, rrtype, pkt, pktlen, 58257403691Sflorian comprloop); 583ae8c6e27Sflorian (*dlen) -= (ordlen-rdlen); 584ae8c6e27Sflorian 585ae8c6e27Sflorian /* default comment */ 586ae8c6e27Sflorian w += sldns_wire2str_rr_comment_print(s, slen, rr, rrlen, dname_off, 587ae8c6e27Sflorian rrtype); 588ae8c6e27Sflorian w += sldns_str_print(s, slen, "\n"); 589ae8c6e27Sflorian return w; 590ae8c6e27Sflorian } 591ae8c6e27Sflorian 592ae8c6e27Sflorian int sldns_wire2str_rrquestion_scan(uint8_t** d, size_t* dlen, char** s, 59357403691Sflorian size_t* slen, uint8_t* pkt, size_t pktlen, int* comprloop) 594ae8c6e27Sflorian { 595ae8c6e27Sflorian int w = 0; 596ae8c6e27Sflorian uint16_t t, c; 59757403691Sflorian w += sldns_wire2str_dname_scan(d, dlen, s, slen, pkt, pktlen, comprloop); 598ae8c6e27Sflorian w += sldns_str_print(s, slen, "\t"); 599ae8c6e27Sflorian if(*dlen < 4) { 600ae8c6e27Sflorian if(*dlen == 0) 601ae8c6e27Sflorian return w + sldns_str_print(s, slen, "Error malformed\n"); 602ae8c6e27Sflorian w += print_remainder_hex("Error malformed 0x", d, dlen, s, slen); 603ae8c6e27Sflorian return w + sldns_str_print(s, slen, "\n"); 604ae8c6e27Sflorian } 605ae8c6e27Sflorian t = sldns_read_uint16(*d); 606ae8c6e27Sflorian c = sldns_read_uint16((*d)+2); 607ae8c6e27Sflorian (*d)+=4; 608ae8c6e27Sflorian (*dlen)-=4; 609ae8c6e27Sflorian w += sldns_wire2str_class_print(s, slen, c); 610ae8c6e27Sflorian w += sldns_str_print(s, slen, "\t"); 611ae8c6e27Sflorian w += sldns_wire2str_type_print(s, slen, t); 612ae8c6e27Sflorian w += sldns_str_print(s, slen, "\n"); 613ae8c6e27Sflorian return w; 614ae8c6e27Sflorian } 615ae8c6e27Sflorian 616ae8c6e27Sflorian int sldns_wire2str_rr_unknown_scan(uint8_t** d, size_t* dlen, char** s, 61757403691Sflorian size_t* slen, uint8_t* pkt, size_t pktlen, int* comprloop) 618ae8c6e27Sflorian { 619ae8c6e27Sflorian size_t rdlen, ordlen; 620ae8c6e27Sflorian int w = 0; 62157403691Sflorian w += sldns_wire2str_dname_scan(d, dlen, s, slen, pkt, pktlen, comprloop); 622ae8c6e27Sflorian w += sldns_str_print(s, slen, "\t"); 623ae8c6e27Sflorian w += sldns_rr_tcttl_scan(d, dlen, s, slen); 624ae8c6e27Sflorian w += sldns_str_print(s, slen, "\t"); 625ae8c6e27Sflorian if(*dlen < 2) { 626ae8c6e27Sflorian if(*dlen == 0) 627ae8c6e27Sflorian return w + sldns_str_print(s, slen, ";Error missing rdatalen\n"); 628ae8c6e27Sflorian w += print_remainder_hex(";Error missing rdatalen 0x", 629ae8c6e27Sflorian d, dlen, s, slen); 630ae8c6e27Sflorian return w + sldns_str_print(s, slen, "\n"); 631ae8c6e27Sflorian } 632ae8c6e27Sflorian rdlen = sldns_read_uint16(*d); 633ae8c6e27Sflorian ordlen = rdlen; 634ae8c6e27Sflorian (*d) += 2; 635ae8c6e27Sflorian (*dlen) -= 2; 636ae8c6e27Sflorian if(*dlen < rdlen) { 637ae8c6e27Sflorian w += sldns_str_print(s, slen, "\\# %u ", (unsigned)rdlen); 638ae8c6e27Sflorian if(*dlen == 0) 639ae8c6e27Sflorian return w + sldns_str_print(s, slen, ";Error missing rdata\n"); 640ae8c6e27Sflorian w += print_remainder_hex(";Error partial rdata 0x", d, dlen, s, slen); 641ae8c6e27Sflorian return w + sldns_str_print(s, slen, "\n"); 642ae8c6e27Sflorian } 643ae8c6e27Sflorian w += sldns_wire2str_rdata_unknown_scan(d, &rdlen, s, slen); 644ae8c6e27Sflorian (*dlen) -= (ordlen-rdlen); 645ae8c6e27Sflorian w += sldns_str_print(s, slen, "\n"); 646ae8c6e27Sflorian return w; 647ae8c6e27Sflorian } 648ae8c6e27Sflorian 649ae8c6e27Sflorian /** print rr comment for type DNSKEY */ 650ae8c6e27Sflorian static int rr_comment_dnskey(char** s, size_t* slen, uint8_t* rr, 651ae8c6e27Sflorian size_t rrlen, size_t dname_off) 652ae8c6e27Sflorian { 653ae8c6e27Sflorian size_t rdlen; 654ae8c6e27Sflorian uint8_t* rdata; 655ae8c6e27Sflorian int flags, w = 0; 656ae8c6e27Sflorian if(rrlen < dname_off + 10) return 0; 657ae8c6e27Sflorian rdlen = sldns_read_uint16(rr+dname_off+8); 658ae8c6e27Sflorian if(rrlen < dname_off + 10 + rdlen) return 0; 65957403691Sflorian if(rdlen < 2) return 0; 660ae8c6e27Sflorian rdata = rr + dname_off + 10; 661ae8c6e27Sflorian flags = (int)sldns_read_uint16(rdata); 662ae8c6e27Sflorian w += sldns_str_print(s, slen, " ;{"); 663ae8c6e27Sflorian 664ae8c6e27Sflorian /* id */ 665ae8c6e27Sflorian w += sldns_str_print(s, slen, "id = %u", 666ae8c6e27Sflorian sldns_calc_keytag_raw(rdata, rdlen)); 667ae8c6e27Sflorian 668ae8c6e27Sflorian /* flags */ 669ae8c6e27Sflorian if((flags&LDNS_KEY_ZONE_KEY)) { 670ae8c6e27Sflorian if((flags&LDNS_KEY_SEP_KEY)) 671ae8c6e27Sflorian w += sldns_str_print(s, slen, " (ksk)"); 672ae8c6e27Sflorian else w += sldns_str_print(s, slen, " (zsk)"); 673ae8c6e27Sflorian } 674ae8c6e27Sflorian 675ae8c6e27Sflorian /* keysize */ 676ae8c6e27Sflorian if(rdlen > 4) { 677ae8c6e27Sflorian w += sldns_str_print(s, slen, ", "); 678ae8c6e27Sflorian w += sldns_str_print(s, slen, "size = %db", 679ae8c6e27Sflorian (int)sldns_rr_dnskey_key_size_raw( 680ae8c6e27Sflorian (unsigned char*)rdata+4, rdlen-4, (int)(rdata[3]))); 681ae8c6e27Sflorian } 682ae8c6e27Sflorian 683ae8c6e27Sflorian w += sldns_str_print(s, slen, "}"); 684ae8c6e27Sflorian return w; 685ae8c6e27Sflorian } 686ae8c6e27Sflorian 687ae8c6e27Sflorian /** print rr comment for type RRSIG */ 688ae8c6e27Sflorian static int rr_comment_rrsig(char** s, size_t* slen, uint8_t* rr, 689ae8c6e27Sflorian size_t rrlen, size_t dname_off) 690ae8c6e27Sflorian { 691ae8c6e27Sflorian size_t rdlen; 692ae8c6e27Sflorian uint8_t* rdata; 693ae8c6e27Sflorian if(rrlen < dname_off + 10) return 0; 694ae8c6e27Sflorian rdlen = sldns_read_uint16(rr+dname_off+8); 695ae8c6e27Sflorian if(rrlen < dname_off + 10 + rdlen) return 0; 696ae8c6e27Sflorian rdata = rr + dname_off + 10; 697ae8c6e27Sflorian if(rdlen < 18) return 0; 698ae8c6e27Sflorian return sldns_str_print(s, slen, " ;{id = %d}", 699ae8c6e27Sflorian (int)sldns_read_uint16(rdata+16)); 700ae8c6e27Sflorian } 701ae8c6e27Sflorian 702ae8c6e27Sflorian /** print rr comment for type NSEC3 */ 703ae8c6e27Sflorian static int rr_comment_nsec3(char** s, size_t* slen, uint8_t* rr, 704ae8c6e27Sflorian size_t rrlen, size_t dname_off) 705ae8c6e27Sflorian { 706ae8c6e27Sflorian size_t rdlen; 707ae8c6e27Sflorian uint8_t* rdata; 708ae8c6e27Sflorian int w = 0; 709ae8c6e27Sflorian if(rrlen < dname_off + 10) return 0; 710ae8c6e27Sflorian rdlen = sldns_read_uint16(rr+dname_off+8); 711ae8c6e27Sflorian if(rrlen < dname_off + 10 + rdlen) return 0; 712ae8c6e27Sflorian rdata = rr + dname_off + 10; 713ae8c6e27Sflorian if(rdlen < 2) return 0; 714ae8c6e27Sflorian if((rdata[1] & LDNS_NSEC3_VARS_OPTOUT_MASK)) 715ae8c6e27Sflorian w += sldns_str_print(s, slen, " ;{flags: optout}"); 716ae8c6e27Sflorian return w; 717ae8c6e27Sflorian } 718ae8c6e27Sflorian 719ae8c6e27Sflorian int sldns_wire2str_rr_comment_print(char** s, size_t* slen, uint8_t* rr, 720ae8c6e27Sflorian size_t rrlen, size_t dname_off, uint16_t rrtype) 721ae8c6e27Sflorian { 722ae8c6e27Sflorian if(rrtype == LDNS_RR_TYPE_DNSKEY) { 723ae8c6e27Sflorian return rr_comment_dnskey(s, slen, rr, rrlen, dname_off); 724ae8c6e27Sflorian } else if(rrtype == LDNS_RR_TYPE_RRSIG) { 725ae8c6e27Sflorian return rr_comment_rrsig(s, slen, rr, rrlen, dname_off); 726ae8c6e27Sflorian } else if(rrtype == LDNS_RR_TYPE_NSEC3) { 727ae8c6e27Sflorian return rr_comment_nsec3(s, slen, rr, rrlen, dname_off); 728ae8c6e27Sflorian } 729ae8c6e27Sflorian return 0; 730ae8c6e27Sflorian } 731ae8c6e27Sflorian 732ae8c6e27Sflorian int sldns_wire2str_header_scan(uint8_t** d, size_t* dlen, char** s, 733ae8c6e27Sflorian size_t* slen) 734ae8c6e27Sflorian { 735ae8c6e27Sflorian int w = 0; 736ae8c6e27Sflorian int opcode, rcode; 737ae8c6e27Sflorian w += sldns_str_print(s, slen, ";; ->>HEADER<<- "); 738ae8c6e27Sflorian if(*dlen == 0) 739ae8c6e27Sflorian return w+sldns_str_print(s, slen, "Error empty packet"); 740ae8c6e27Sflorian if(*dlen < 4) 741ae8c6e27Sflorian return w+print_remainder_hex("Error header too short 0x", d, dlen, s, slen); 742ae8c6e27Sflorian opcode = (int)LDNS_OPCODE_WIRE(*d); 743ae8c6e27Sflorian rcode = (int)LDNS_RCODE_WIRE(*d); 744ae8c6e27Sflorian w += sldns_str_print(s, slen, "opcode: "); 745ae8c6e27Sflorian w += sldns_wire2str_opcode_print(s, slen, opcode); 746ae8c6e27Sflorian w += sldns_str_print(s, slen, ", "); 747ae8c6e27Sflorian w += sldns_str_print(s, slen, "rcode: "); 748ae8c6e27Sflorian w += sldns_wire2str_rcode_print(s, slen, rcode); 749ae8c6e27Sflorian w += sldns_str_print(s, slen, ", "); 750ae8c6e27Sflorian w += sldns_str_print(s, slen, "id: %d\n", (int)LDNS_ID_WIRE(*d)); 751ae8c6e27Sflorian w += sldns_str_print(s, slen, ";; flags:"); 752ae8c6e27Sflorian if(LDNS_QR_WIRE(*d)) w += sldns_str_print(s, slen, " qr"); 753ae8c6e27Sflorian if(LDNS_AA_WIRE(*d)) w += sldns_str_print(s, slen, " aa"); 754ae8c6e27Sflorian if(LDNS_TC_WIRE(*d)) w += sldns_str_print(s, slen, " tc"); 755ae8c6e27Sflorian if(LDNS_RD_WIRE(*d)) w += sldns_str_print(s, slen, " rd"); 756ae8c6e27Sflorian if(LDNS_CD_WIRE(*d)) w += sldns_str_print(s, slen, " cd"); 757ae8c6e27Sflorian if(LDNS_RA_WIRE(*d)) w += sldns_str_print(s, slen, " ra"); 758ae8c6e27Sflorian if(LDNS_AD_WIRE(*d)) w += sldns_str_print(s, slen, " ad"); 759ae8c6e27Sflorian if(LDNS_Z_WIRE(*d)) w += sldns_str_print(s, slen, " z"); 760ae8c6e27Sflorian w += sldns_str_print(s, slen, " ; "); 761ae8c6e27Sflorian if(*dlen < LDNS_HEADER_SIZE) 762ae8c6e27Sflorian return w+print_remainder_hex("Error header too short 0x", d, dlen, s, slen); 763ae8c6e27Sflorian w += sldns_str_print(s, slen, "QUERY: %d, ", (int)LDNS_QDCOUNT(*d)); 764ae8c6e27Sflorian w += sldns_str_print(s, slen, "ANSWER: %d, ", (int)LDNS_ANCOUNT(*d)); 765ae8c6e27Sflorian w += sldns_str_print(s, slen, "AUTHORITY: %d, ", (int)LDNS_NSCOUNT(*d)); 766ae8c6e27Sflorian w += sldns_str_print(s, slen, "ADDITIONAL: %d ", (int)LDNS_ARCOUNT(*d)); 767ae8c6e27Sflorian *d += LDNS_HEADER_SIZE; 768ae8c6e27Sflorian *dlen -= LDNS_HEADER_SIZE; 769ae8c6e27Sflorian return w; 770ae8c6e27Sflorian } 771ae8c6e27Sflorian 772ae8c6e27Sflorian int sldns_wire2str_rdata_scan(uint8_t** d, size_t* dlen, char** s, 77357403691Sflorian size_t* slen, uint16_t rrtype, uint8_t* pkt, size_t pktlen, 77457403691Sflorian int* comprloop) 775ae8c6e27Sflorian { 776ae8c6e27Sflorian /* try to prettyprint, but if that fails, use unknown format */ 777ae8c6e27Sflorian uint8_t* origd = *d; 778ae8c6e27Sflorian char* origs = *s; 779ae8c6e27Sflorian size_t origdlen = *dlen, origslen = *slen; 780ae8c6e27Sflorian size_t r_cnt, r_max; 781ae8c6e27Sflorian sldns_rdf_type rdftype; 782ae8c6e27Sflorian int w = 0, n; 783ae8c6e27Sflorian 784ae8c6e27Sflorian const sldns_rr_descriptor *desc = sldns_rr_descript(rrtype); 785ae8c6e27Sflorian if(!desc) /* unknown format */ 786ae8c6e27Sflorian return sldns_wire2str_rdata_unknown_scan(d, dlen, s, slen); 787ae8c6e27Sflorian /* dlen equals the rdatalen for the rdata */ 788ae8c6e27Sflorian 789ae8c6e27Sflorian r_max = sldns_rr_descriptor_maximum(desc); 790ae8c6e27Sflorian for(r_cnt=0; r_cnt < r_max; r_cnt++) { 791ae8c6e27Sflorian if(*dlen == 0) { 792ae8c6e27Sflorian if(r_cnt < sldns_rr_descriptor_minimum(desc)) 793ae8c6e27Sflorian goto failed; 794ae8c6e27Sflorian break; /* nothing more to print */ 795ae8c6e27Sflorian } 796ae8c6e27Sflorian rdftype = sldns_rr_descriptor_field_type(desc, r_cnt); 797ae8c6e27Sflorian if(r_cnt != 0) 798ae8c6e27Sflorian w += sldns_str_print(s, slen, " "); 799ae8c6e27Sflorian n = sldns_wire2str_rdf_scan(d, dlen, s, slen, rdftype, 80057403691Sflorian pkt, pktlen, comprloop); 801ae8c6e27Sflorian if(n == -1) { 802ae8c6e27Sflorian failed: 803ae8c6e27Sflorian /* failed, use unknown format */ 804ae8c6e27Sflorian *d = origd; *s = origs; 805ae8c6e27Sflorian *dlen = origdlen; *slen = origslen; 806ae8c6e27Sflorian return sldns_wire2str_rdata_unknown_scan(d, dlen, 807ae8c6e27Sflorian s, slen); 808ae8c6e27Sflorian } 809ae8c6e27Sflorian w += n; 810ae8c6e27Sflorian } 811ae8c6e27Sflorian if(*dlen != 0) { 812ae8c6e27Sflorian goto failed; 813ae8c6e27Sflorian } 814ae8c6e27Sflorian return w; 815ae8c6e27Sflorian } 816ae8c6e27Sflorian 817ae8c6e27Sflorian int sldns_wire2str_rdata_unknown_scan(uint8_t** d, size_t* dlen, char** s, 818ae8c6e27Sflorian size_t* slen) 819ae8c6e27Sflorian { 820ae8c6e27Sflorian int w = 0; 821ae8c6e27Sflorian 822ae8c6e27Sflorian /* print length */ 823ae8c6e27Sflorian w += sldns_str_print(s, slen, "\\# %u", (unsigned)*dlen); 824ae8c6e27Sflorian 825ae8c6e27Sflorian /* print rdlen in hex */ 826ae8c6e27Sflorian if(*dlen != 0) 827ae8c6e27Sflorian w += sldns_str_print(s, slen, " "); 828ae8c6e27Sflorian w += print_hex_buf(s, slen, *d, *dlen); 829ae8c6e27Sflorian (*d) += *dlen; 830ae8c6e27Sflorian (*dlen) = 0; 831ae8c6e27Sflorian return w; 832ae8c6e27Sflorian } 833ae8c6e27Sflorian 834ae8c6e27Sflorian /** print and escape one character for a domain dname */ 835ae8c6e27Sflorian static int dname_char_print(char** s, size_t* slen, uint8_t c) 836ae8c6e27Sflorian { 837ae8c6e27Sflorian if(c == '.' || c == ';' || c == '(' || c == ')' || c == '\\') 838ae8c6e27Sflorian return sldns_str_print(s, slen, "\\%c", c); 839ae8c6e27Sflorian else if(!(isascii((unsigned char)c) && isgraph((unsigned char)c))) 840ae8c6e27Sflorian return sldns_str_print(s, slen, "\\%03u", (unsigned)c); 841ae8c6e27Sflorian /* plain printout */ 842ae8c6e27Sflorian if(*slen) { 843ae8c6e27Sflorian **s = (char)c; 844ae8c6e27Sflorian (*s)++; 845ae8c6e27Sflorian (*slen)--; 846ae8c6e27Sflorian } 847ae8c6e27Sflorian return 1; 848ae8c6e27Sflorian } 849ae8c6e27Sflorian 850ae8c6e27Sflorian int sldns_wire2str_dname_scan(uint8_t** d, size_t* dlen, char** s, size_t* slen, 85157403691Sflorian uint8_t* pkt, size_t pktlen, int* comprloop) 852ae8c6e27Sflorian { 853ae8c6e27Sflorian int w = 0; 854ae8c6e27Sflorian /* spool labels onto the string, use compression if its there */ 855ae8c6e27Sflorian uint8_t* pos = *d; 856ae8c6e27Sflorian unsigned i, counter=0; 85757403691Sflorian unsigned maxcompr = MAX_COMPRESS_PTRS; /* loop detection, max compr ptrs */ 858ae8c6e27Sflorian int in_buf = 1; 859a1a7ba80Sflorian size_t dname_len = 0; 86057403691Sflorian if(comprloop) { 86157403691Sflorian if(*comprloop != 0) 86257403691Sflorian maxcompr = 30; /* for like ipv6 reverse name, per label */ 86357403691Sflorian if(*comprloop > 4) 86457403691Sflorian maxcompr = 4; /* just don't want to spend time, any more */ 86557403691Sflorian } 866ae8c6e27Sflorian if(*dlen == 0) return sldns_str_print(s, slen, "ErrorMissingDname"); 867ae8c6e27Sflorian if(*pos == 0) { 868ae8c6e27Sflorian (*d)++; 869ae8c6e27Sflorian (*dlen)--; 870ae8c6e27Sflorian return sldns_str_print(s, slen, "."); 871ae8c6e27Sflorian } 87257403691Sflorian while((!pkt || pos < pkt+pktlen) && *pos) { 873ae8c6e27Sflorian /* read label length */ 874ae8c6e27Sflorian uint8_t labellen = *pos++; 875ae8c6e27Sflorian if(in_buf) { (*d)++; (*dlen)--; } 876ae8c6e27Sflorian 877ae8c6e27Sflorian /* find out what sort of label we have */ 878ae8c6e27Sflorian if((labellen&0xc0) == 0xc0) { 879ae8c6e27Sflorian /* compressed */ 880ae8c6e27Sflorian uint16_t target = 0; 881ae8c6e27Sflorian if(in_buf && *dlen == 0) 882ae8c6e27Sflorian return w + sldns_str_print(s, slen, 883ae8c6e27Sflorian "ErrorPartialDname"); 884ae8c6e27Sflorian else if(!in_buf && pos+1 > pkt+pktlen) 885ae8c6e27Sflorian return w + sldns_str_print(s, slen, 886ae8c6e27Sflorian "ErrorPartialDname"); 887ae8c6e27Sflorian target = ((labellen&0x3f)<<8) | *pos; 888ae8c6e27Sflorian if(in_buf) { (*d)++; (*dlen)--; } 889ae8c6e27Sflorian /* move to target, if possible */ 890ae8c6e27Sflorian if(!pkt || target >= pktlen) 891ae8c6e27Sflorian return w + sldns_str_print(s, slen, 892ae8c6e27Sflorian "ErrorComprPtrOutOfBounds"); 89357403691Sflorian if(counter++ > maxcompr) { 89457403691Sflorian if(comprloop && *comprloop < 10) 89557403691Sflorian (*comprloop)++; 896ae8c6e27Sflorian return w + sldns_str_print(s, slen, 897ae8c6e27Sflorian "ErrorComprPtrLooped"); 89857403691Sflorian } 899ae8c6e27Sflorian in_buf = 0; 900ae8c6e27Sflorian pos = pkt+target; 901ae8c6e27Sflorian continue; 902ae8c6e27Sflorian } else if((labellen&0xc0)) { 903ae8c6e27Sflorian /* notimpl label type */ 904ae8c6e27Sflorian w += sldns_str_print(s, slen, 905ae8c6e27Sflorian "ErrorLABELTYPE%xIsUnknown", 906ae8c6e27Sflorian (int)(labellen&0xc0)); 907ae8c6e27Sflorian return w; 908ae8c6e27Sflorian } 909ae8c6e27Sflorian 910ae8c6e27Sflorian /* spool label characters, end with '.' */ 911ae8c6e27Sflorian if(in_buf && *dlen < (size_t)labellen) 912ae8c6e27Sflorian labellen = (uint8_t)*dlen; 913ae8c6e27Sflorian else if(!in_buf && pos+(size_t)labellen > pkt+pktlen) 914ae8c6e27Sflorian labellen = (uint8_t)(pkt + pktlen - pos); 915a1a7ba80Sflorian dname_len += ((size_t)labellen)+1; 916a1a7ba80Sflorian if(dname_len > LDNS_MAX_DOMAINLEN) { 917a1a7ba80Sflorian /* dname_len counts the uncompressed length we have 918a1a7ba80Sflorian * seen so far, and the domain name has become too 919a1a7ba80Sflorian * long, prevent the loop from printing overly long 920a1a7ba80Sflorian * content. */ 921a1a7ba80Sflorian w += sldns_str_print(s, slen, 922a1a7ba80Sflorian "ErrorDomainNameTooLong"); 923a1a7ba80Sflorian return w; 924a1a7ba80Sflorian } 925ae8c6e27Sflorian for(i=0; i<(unsigned)labellen; i++) { 926ae8c6e27Sflorian w += dname_char_print(s, slen, *pos++); 927ae8c6e27Sflorian } 928ae8c6e27Sflorian if(in_buf) { 929ae8c6e27Sflorian (*d) += labellen; 930ae8c6e27Sflorian (*dlen) -= labellen; 931ae8c6e27Sflorian if(*dlen == 0) break; 932ae8c6e27Sflorian } 933ae8c6e27Sflorian w += sldns_str_print(s, slen, "."); 934ae8c6e27Sflorian } 935ae8c6e27Sflorian /* skip over final root label */ 936ae8c6e27Sflorian if(in_buf && *dlen > 0) { (*d)++; (*dlen)--; } 937ae8c6e27Sflorian /* in case we printed no labels, terminate dname */ 938ae8c6e27Sflorian if(w == 0) w += sldns_str_print(s, slen, "."); 939ae8c6e27Sflorian return w; 940ae8c6e27Sflorian } 941ae8c6e27Sflorian 942ae8c6e27Sflorian int sldns_wire2str_opcode_print(char** s, size_t* slen, int opcode) 943ae8c6e27Sflorian { 944ae8c6e27Sflorian sldns_lookup_table *lt = sldns_lookup_by_id(sldns_opcodes, opcode); 945ae8c6e27Sflorian if (lt && lt->name) { 946ae8c6e27Sflorian return sldns_str_print(s, slen, "%s", lt->name); 947ae8c6e27Sflorian } 948ae8c6e27Sflorian return sldns_str_print(s, slen, "OPCODE%u", (unsigned)opcode); 949ae8c6e27Sflorian } 950ae8c6e27Sflorian 951ae8c6e27Sflorian int sldns_wire2str_rcode_print(char** s, size_t* slen, int rcode) 952ae8c6e27Sflorian { 953ae8c6e27Sflorian sldns_lookup_table *lt = sldns_lookup_by_id(sldns_rcodes, rcode); 954ae8c6e27Sflorian if (lt && lt->name) { 955ae8c6e27Sflorian return sldns_str_print(s, slen, "%s", lt->name); 956ae8c6e27Sflorian } 957ae8c6e27Sflorian return sldns_str_print(s, slen, "RCODE%u", (unsigned)rcode); 958ae8c6e27Sflorian } 959ae8c6e27Sflorian 960ae8c6e27Sflorian int sldns_wire2str_class_print(char** s, size_t* slen, uint16_t rrclass) 961ae8c6e27Sflorian { 962ae8c6e27Sflorian sldns_lookup_table *lt = sldns_lookup_by_id(sldns_rr_classes, 963ae8c6e27Sflorian (int)rrclass); 964ae8c6e27Sflorian if (lt && lt->name) { 965ae8c6e27Sflorian return sldns_str_print(s, slen, "%s", lt->name); 966ae8c6e27Sflorian } 967ae8c6e27Sflorian return sldns_str_print(s, slen, "CLASS%u", (unsigned)rrclass); 968ae8c6e27Sflorian } 969ae8c6e27Sflorian 970ae8c6e27Sflorian int sldns_wire2str_type_print(char** s, size_t* slen, uint16_t rrtype) 971ae8c6e27Sflorian { 972ae8c6e27Sflorian const sldns_rr_descriptor *descriptor = sldns_rr_descript(rrtype); 973ae8c6e27Sflorian if (descriptor && descriptor->_name) { 974ae8c6e27Sflorian return sldns_str_print(s, slen, "%s", descriptor->_name); 975ae8c6e27Sflorian } 976ae8c6e27Sflorian return sldns_str_print(s, slen, "TYPE%u", (unsigned)rrtype); 977ae8c6e27Sflorian } 978ae8c6e27Sflorian 979ae8c6e27Sflorian int sldns_wire2str_edns_option_code_print(char** s, size_t* slen, 980ae8c6e27Sflorian uint16_t opcode) 981ae8c6e27Sflorian { 982ae8c6e27Sflorian sldns_lookup_table *lt = sldns_lookup_by_id(sldns_edns_options, 983ae8c6e27Sflorian (int)opcode); 984ae8c6e27Sflorian if (lt && lt->name) { 985ae8c6e27Sflorian return sldns_str_print(s, slen, "%s", lt->name); 986ae8c6e27Sflorian } 987ae8c6e27Sflorian return sldns_str_print(s, slen, "OPT%u", (unsigned)opcode); 988ae8c6e27Sflorian } 989ae8c6e27Sflorian 990ae8c6e27Sflorian int sldns_wire2str_class_scan(uint8_t** d, size_t* dlen, char** s, size_t* slen) 991ae8c6e27Sflorian { 992ae8c6e27Sflorian uint16_t c; 993ae8c6e27Sflorian if(*dlen == 0) return 0; 994ae8c6e27Sflorian if(*dlen < 2) return print_remainder_hex("Error malformed 0x", d, dlen, s, slen); 995ae8c6e27Sflorian c = sldns_read_uint16(*d); 996ae8c6e27Sflorian (*d)+=2; 997ae8c6e27Sflorian (*dlen)-=2; 998ae8c6e27Sflorian return sldns_wire2str_class_print(s, slen, c); 999ae8c6e27Sflorian } 1000ae8c6e27Sflorian 1001ae8c6e27Sflorian int sldns_wire2str_type_scan(uint8_t** d, size_t* dlen, char** s, size_t* slen) 1002ae8c6e27Sflorian { 1003ae8c6e27Sflorian uint16_t t; 1004ae8c6e27Sflorian if(*dlen == 0) return 0; 1005ae8c6e27Sflorian if(*dlen < 2) return print_remainder_hex("Error malformed 0x", d, dlen, s, slen); 1006ae8c6e27Sflorian t = sldns_read_uint16(*d); 1007ae8c6e27Sflorian (*d)+=2; 1008ae8c6e27Sflorian (*dlen)-=2; 1009ae8c6e27Sflorian return sldns_wire2str_type_print(s, slen, t); 1010ae8c6e27Sflorian } 1011ae8c6e27Sflorian 1012ae8c6e27Sflorian int sldns_wire2str_ttl_scan(uint8_t** d, size_t* dlen, char** s, size_t* slen) 1013ae8c6e27Sflorian { 1014ae8c6e27Sflorian uint32_t ttl; 1015ae8c6e27Sflorian if(*dlen == 0) return 0; 1016ae8c6e27Sflorian if(*dlen < 4) return print_remainder_hex("Error malformed 0x", d, dlen, s, slen); 1017ae8c6e27Sflorian ttl = sldns_read_uint32(*d); 1018ae8c6e27Sflorian (*d)+=4; 1019ae8c6e27Sflorian (*dlen)-=4; 1020ae8c6e27Sflorian return sldns_str_print(s, slen, "%u", (unsigned)ttl); 1021ae8c6e27Sflorian } 1022ae8c6e27Sflorian 1023411c5950Sflorian static int 1024411c5950Sflorian sldns_print_svcparamkey(char** s, size_t* slen, uint16_t svcparamkey) 1025411c5950Sflorian { 1026411c5950Sflorian if (svcparamkey < SVCPARAMKEY_COUNT) { 1027411c5950Sflorian return sldns_str_print(s, slen, "%s", svcparamkey_strs[svcparamkey]); 1028411c5950Sflorian } 1029411c5950Sflorian else { 1030411c5950Sflorian return sldns_str_print(s, slen, "key%d", (int)svcparamkey); 1031411c5950Sflorian } 1032411c5950Sflorian } 1033411c5950Sflorian 1034411c5950Sflorian static int sldns_wire2str_svcparam_port2str(char** s, 1035411c5950Sflorian size_t* slen, uint16_t data_len, uint8_t* data) 1036411c5950Sflorian { 1037411c5950Sflorian int w = 0; 1038411c5950Sflorian 1039411c5950Sflorian if (data_len != 2) 1040411c5950Sflorian return -1; /* wireformat error, a short is 2 bytes */ 1041411c5950Sflorian w = sldns_str_print(s, slen, "=%d", (int)sldns_read_uint16(data)); 1042411c5950Sflorian 1043411c5950Sflorian return w; 1044411c5950Sflorian } 1045411c5950Sflorian 1046411c5950Sflorian static int sldns_wire2str_svcparam_ipv4hint2str(char** s, 1047411c5950Sflorian size_t* slen, uint16_t data_len, uint8_t* data) 1048411c5950Sflorian { 1049411c5950Sflorian char ip_str[INET_ADDRSTRLEN + 1]; 1050411c5950Sflorian 1051411c5950Sflorian int w = 0; 1052411c5950Sflorian 1053411c5950Sflorian assert(data_len > 0); 1054411c5950Sflorian 1055411c5950Sflorian if ((data_len % LDNS_IP4ADDRLEN) == 0) { 1056411c5950Sflorian if (inet_ntop(AF_INET, data, ip_str, sizeof(ip_str)) == NULL) 1057411c5950Sflorian return -1; /* wireformat error, incorrect size or inet family */ 1058411c5950Sflorian 1059411c5950Sflorian w += sldns_str_print(s, slen, "=%s", ip_str); 1060411c5950Sflorian data += LDNS_IP4ADDRLEN; 1061411c5950Sflorian 1062411c5950Sflorian while ((data_len -= LDNS_IP4ADDRLEN) > 0) { 1063411c5950Sflorian if (inet_ntop(AF_INET, data, ip_str, sizeof(ip_str)) == NULL) 1064411c5950Sflorian return -1; /* wireformat error, incorrect size or inet family */ 1065411c5950Sflorian 1066411c5950Sflorian w += sldns_str_print(s, slen, ",%s", ip_str); 1067411c5950Sflorian data += LDNS_IP4ADDRLEN; 1068411c5950Sflorian } 1069411c5950Sflorian } else 1070411c5950Sflorian return -1; 1071411c5950Sflorian 1072411c5950Sflorian return w; 1073411c5950Sflorian } 1074411c5950Sflorian 1075411c5950Sflorian static int sldns_wire2str_svcparam_ipv6hint2str(char** s, 1076411c5950Sflorian size_t* slen, uint16_t data_len, uint8_t* data) 1077411c5950Sflorian { 1078411c5950Sflorian char ip_str[INET6_ADDRSTRLEN + 1]; 1079411c5950Sflorian 1080411c5950Sflorian int w = 0; 1081411c5950Sflorian 1082411c5950Sflorian assert(data_len > 0); 1083411c5950Sflorian 1084411c5950Sflorian if ((data_len % LDNS_IP6ADDRLEN) == 0) { 1085411c5950Sflorian if (inet_ntop(AF_INET6, data, ip_str, sizeof(ip_str)) == NULL) 1086411c5950Sflorian return -1; /* wireformat error, incorrect size or inet family */ 1087411c5950Sflorian 1088411c5950Sflorian w += sldns_str_print(s, slen, "=%s", ip_str); 1089411c5950Sflorian data += LDNS_IP6ADDRLEN; 1090411c5950Sflorian 1091411c5950Sflorian while ((data_len -= LDNS_IP6ADDRLEN) > 0) { 1092411c5950Sflorian if (inet_ntop(AF_INET6, data, ip_str, sizeof(ip_str)) == NULL) 1093411c5950Sflorian return -1; /* wireformat error, incorrect size or inet family */ 1094411c5950Sflorian 1095411c5950Sflorian w += sldns_str_print(s, slen, ",%s", ip_str); 1096411c5950Sflorian data += LDNS_IP6ADDRLEN; 1097411c5950Sflorian } 1098411c5950Sflorian } else 1099411c5950Sflorian return -1; 1100411c5950Sflorian 1101411c5950Sflorian return w; 1102411c5950Sflorian } 1103411c5950Sflorian 1104411c5950Sflorian static int sldns_wire2str_svcparam_mandatory2str(char** s, 1105411c5950Sflorian size_t* slen, uint16_t data_len, uint8_t* data) 1106411c5950Sflorian { 1107411c5950Sflorian int w = 0; 1108411c5950Sflorian 1109411c5950Sflorian assert(data_len > 0); 1110411c5950Sflorian 1111411c5950Sflorian if (data_len % sizeof(uint16_t)) 11126d08cb1bSflorian return -1; /* wireformat error, data_len must be multiple of shorts */ 1113411c5950Sflorian w += sldns_str_print(s, slen, "="); 1114411c5950Sflorian w += sldns_print_svcparamkey(s, slen, sldns_read_uint16(data)); 1115411c5950Sflorian data += 2; 1116411c5950Sflorian 1117411c5950Sflorian while ((data_len -= sizeof(uint16_t))) { 1118411c5950Sflorian w += sldns_str_print(s, slen, ","); 1119411c5950Sflorian w += sldns_print_svcparamkey(s, slen, sldns_read_uint16(data)); 1120411c5950Sflorian data += 2; 1121411c5950Sflorian } 1122411c5950Sflorian 1123411c5950Sflorian return w; 1124411c5950Sflorian } 1125411c5950Sflorian 1126411c5950Sflorian static int sldns_wire2str_svcparam_alpn2str(char** s, 1127411c5950Sflorian size_t* slen, uint16_t data_len, uint8_t* data) 1128411c5950Sflorian { 1129411c5950Sflorian uint8_t *dp = (void *)data; 1130411c5950Sflorian int w = 0; 1131411c5950Sflorian 1132411c5950Sflorian assert(data_len > 0); /* Guaranteed by sldns_wire2str_svcparam_scan */ 1133411c5950Sflorian 1134411c5950Sflorian w += sldns_str_print(s, slen, "=\""); 1135411c5950Sflorian while (data_len) { 1136411c5950Sflorian /* alpn is list of length byte (str_len) followed by a string of that size */ 1137411c5950Sflorian uint8_t i, str_len = *dp++; 1138411c5950Sflorian 1139411c5950Sflorian if (str_len > --data_len) 1140411c5950Sflorian return -1; 1141411c5950Sflorian 1142411c5950Sflorian for (i = 0; i < str_len; i++) { 1143411c5950Sflorian if (dp[i] == '"' || dp[i] == '\\') 1144411c5950Sflorian w += sldns_str_print(s, slen, "\\\\\\%c", dp[i]); 1145411c5950Sflorian 1146411c5950Sflorian else if (dp[i] == ',') 1147411c5950Sflorian w += sldns_str_print(s, slen, "\\\\%c", dp[i]); 1148411c5950Sflorian 1149411c5950Sflorian else if (!isprint(dp[i])) 1150411c5950Sflorian w += sldns_str_print(s, slen, "\\%03u", (unsigned) dp[i]); 1151411c5950Sflorian 1152411c5950Sflorian else 1153411c5950Sflorian w += sldns_str_print(s, slen, "%c", dp[i]); 1154411c5950Sflorian } 1155411c5950Sflorian dp += str_len; 1156411c5950Sflorian if ((data_len -= str_len)) 1157411c5950Sflorian w += sldns_str_print(s, slen, "%s", ","); 1158411c5950Sflorian } 1159411c5950Sflorian w += sldns_str_print(s, slen, "\""); 1160411c5950Sflorian 1161411c5950Sflorian return w; 1162411c5950Sflorian } 1163411c5950Sflorian 1164411c5950Sflorian static int sldns_wire2str_svcparam_ech2str(char** s, 1165411c5950Sflorian size_t* slen, uint16_t data_len, uint8_t* data) 1166411c5950Sflorian { 1167411c5950Sflorian int size; 1168411c5950Sflorian int w = 0; 1169411c5950Sflorian 1170411c5950Sflorian assert(data_len > 0); /* Guaranteed by sldns_wire2str_svcparam_scan */ 1171411c5950Sflorian 1172411c5950Sflorian w += sldns_str_print(s, slen, "=\""); 1173411c5950Sflorian 1174411c5950Sflorian if ((size = sldns_b64_ntop(data, data_len, *s, *slen)) < 0) 1175411c5950Sflorian return -1; 1176411c5950Sflorian 1177411c5950Sflorian (*s) += size; 1178411c5950Sflorian (*slen) -= size; 1179411c5950Sflorian 1180411c5950Sflorian w += sldns_str_print(s, slen, "\""); 1181411c5950Sflorian 1182411c5950Sflorian return w + size; 1183411c5950Sflorian } 1184411c5950Sflorian 1185411c5950Sflorian int sldns_wire2str_svcparam_scan(uint8_t** d, size_t* dlen, char** s, size_t* slen) 1186411c5950Sflorian { 1187411c5950Sflorian uint8_t ch; 1188411c5950Sflorian uint16_t svcparamkey, data_len; 1189411c5950Sflorian int written_chars = 0; 1190411c5950Sflorian int r, i; 1191411c5950Sflorian 1192411c5950Sflorian /* verify that we have enough data to read svcparamkey and data_len */ 1193411c5950Sflorian if(*dlen < 4) 1194411c5950Sflorian return -1; 1195411c5950Sflorian 1196411c5950Sflorian svcparamkey = sldns_read_uint16(*d); 1197411c5950Sflorian data_len = sldns_read_uint16(*d+2); 1198411c5950Sflorian *d += 4; 1199411c5950Sflorian *dlen -= 4; 1200411c5950Sflorian 1201411c5950Sflorian /* verify that we have data_len data */ 1202411c5950Sflorian if (data_len > *dlen) 1203411c5950Sflorian return -1; 1204411c5950Sflorian 1205411c5950Sflorian written_chars += sldns_print_svcparamkey(s, slen, svcparamkey); 1206411c5950Sflorian if (!data_len) { 1207411c5950Sflorian 1208411c5950Sflorian /* Some SvcParams MUST have values */ 1209411c5950Sflorian switch (svcparamkey) { 1210411c5950Sflorian case SVCB_KEY_ALPN: 1211411c5950Sflorian case SVCB_KEY_PORT: 1212411c5950Sflorian case SVCB_KEY_IPV4HINT: 1213411c5950Sflorian case SVCB_KEY_IPV6HINT: 1214411c5950Sflorian case SVCB_KEY_MANDATORY: 1215d500c338Sflorian case SVCB_KEY_DOHPATH: 1216411c5950Sflorian return -1; 1217411c5950Sflorian default: 1218411c5950Sflorian return written_chars; 1219411c5950Sflorian } 1220411c5950Sflorian } 1221411c5950Sflorian 1222411c5950Sflorian switch (svcparamkey) { 1223411c5950Sflorian case SVCB_KEY_PORT: 1224411c5950Sflorian r = sldns_wire2str_svcparam_port2str(s, slen, data_len, *d); 1225411c5950Sflorian break; 1226411c5950Sflorian case SVCB_KEY_IPV4HINT: 1227411c5950Sflorian r = sldns_wire2str_svcparam_ipv4hint2str(s, slen, data_len, *d); 1228411c5950Sflorian break; 1229411c5950Sflorian case SVCB_KEY_IPV6HINT: 1230411c5950Sflorian r = sldns_wire2str_svcparam_ipv6hint2str(s, slen, data_len, *d); 1231411c5950Sflorian break; 1232411c5950Sflorian case SVCB_KEY_MANDATORY: 1233411c5950Sflorian r = sldns_wire2str_svcparam_mandatory2str(s, slen, data_len, *d); 1234411c5950Sflorian break; 1235411c5950Sflorian case SVCB_KEY_NO_DEFAULT_ALPN: 1236411c5950Sflorian return -1; /* wireformat error, should not have a value */ 1237411c5950Sflorian case SVCB_KEY_ALPN: 1238411c5950Sflorian r = sldns_wire2str_svcparam_alpn2str(s, slen, data_len, *d); 1239411c5950Sflorian break; 1240411c5950Sflorian case SVCB_KEY_ECH: 1241411c5950Sflorian r = sldns_wire2str_svcparam_ech2str(s, slen, data_len, *d); 1242411c5950Sflorian break; 1243d500c338Sflorian case SVCB_KEY_DOHPATH: 1244*7037e34cSflorian ATTR_FALLTHROUGH 1245d500c338Sflorian /* fallthrough */ 1246411c5950Sflorian default: 1247411c5950Sflorian r = sldns_str_print(s, slen, "=\""); 1248411c5950Sflorian 1249411c5950Sflorian for (i = 0; i < data_len; i++) { 1250411c5950Sflorian ch = (*d)[i]; 1251411c5950Sflorian 1252411c5950Sflorian if (ch == '"' || ch == '\\') 1253411c5950Sflorian r += sldns_str_print(s, slen, "\\%c", ch); 1254411c5950Sflorian 1255411c5950Sflorian else if (!isprint(ch)) 1256411c5950Sflorian r += sldns_str_print(s, slen, "\\%03u", (unsigned) ch); 1257411c5950Sflorian 1258411c5950Sflorian else 1259411c5950Sflorian r += sldns_str_print(s, slen, "%c", ch); 1260411c5950Sflorian 1261411c5950Sflorian } 1262411c5950Sflorian r += sldns_str_print(s, slen, "\""); 1263411c5950Sflorian break; 1264411c5950Sflorian } 1265411c5950Sflorian if (r <= 0) 1266411c5950Sflorian return -1; /* wireformat error */ 1267411c5950Sflorian 1268411c5950Sflorian written_chars += r; 1269411c5950Sflorian *d += data_len; 1270411c5950Sflorian *dlen -= data_len; 1271411c5950Sflorian return written_chars; 1272411c5950Sflorian } 1273411c5950Sflorian 1274ae8c6e27Sflorian int sldns_wire2str_rdf_scan(uint8_t** d, size_t* dlen, char** s, size_t* slen, 127557403691Sflorian int rdftype, uint8_t* pkt, size_t pktlen, int* comprloop) 1276ae8c6e27Sflorian { 1277ae8c6e27Sflorian if(*dlen == 0) return 0; 1278ae8c6e27Sflorian switch(rdftype) { 1279ae8c6e27Sflorian case LDNS_RDF_TYPE_NONE: 1280ae8c6e27Sflorian return 0; 1281ae8c6e27Sflorian case LDNS_RDF_TYPE_DNAME: 128257403691Sflorian return sldns_wire2str_dname_scan(d, dlen, s, slen, pkt, pktlen, comprloop); 1283ae8c6e27Sflorian case LDNS_RDF_TYPE_INT8: 1284ae8c6e27Sflorian return sldns_wire2str_int8_scan(d, dlen, s, slen); 1285ae8c6e27Sflorian case LDNS_RDF_TYPE_INT16: 1286ae8c6e27Sflorian return sldns_wire2str_int16_scan(d, dlen, s, slen); 1287ae8c6e27Sflorian case LDNS_RDF_TYPE_INT32: 1288ae8c6e27Sflorian return sldns_wire2str_int32_scan(d, dlen, s, slen); 1289ae8c6e27Sflorian case LDNS_RDF_TYPE_PERIOD: 1290ae8c6e27Sflorian return sldns_wire2str_period_scan(d, dlen, s, slen); 1291ae8c6e27Sflorian case LDNS_RDF_TYPE_TSIGTIME: 1292ae8c6e27Sflorian return sldns_wire2str_tsigtime_scan(d, dlen, s, slen); 1293ae8c6e27Sflorian case LDNS_RDF_TYPE_A: 1294ae8c6e27Sflorian return sldns_wire2str_a_scan(d, dlen, s, slen); 1295ae8c6e27Sflorian case LDNS_RDF_TYPE_AAAA: 1296ae8c6e27Sflorian return sldns_wire2str_aaaa_scan(d, dlen, s, slen); 1297ae8c6e27Sflorian case LDNS_RDF_TYPE_STR: 1298ae8c6e27Sflorian return sldns_wire2str_str_scan(d, dlen, s, slen); 1299ae8c6e27Sflorian case LDNS_RDF_TYPE_APL: 1300ae8c6e27Sflorian return sldns_wire2str_apl_scan(d, dlen, s, slen); 1301ae8c6e27Sflorian case LDNS_RDF_TYPE_B32_EXT: 1302ae8c6e27Sflorian return sldns_wire2str_b32_ext_scan(d, dlen, s, slen); 1303ae8c6e27Sflorian case LDNS_RDF_TYPE_B64: 1304ae8c6e27Sflorian return sldns_wire2str_b64_scan(d, dlen, s, slen); 1305ae8c6e27Sflorian case LDNS_RDF_TYPE_HEX: 1306ae8c6e27Sflorian return sldns_wire2str_hex_scan(d, dlen, s, slen); 1307ae8c6e27Sflorian case LDNS_RDF_TYPE_NSEC: 1308ae8c6e27Sflorian return sldns_wire2str_nsec_scan(d, dlen, s, slen); 1309ae8c6e27Sflorian case LDNS_RDF_TYPE_NSEC3_SALT: 1310ae8c6e27Sflorian return sldns_wire2str_nsec3_salt_scan(d, dlen, s, slen); 1311ae8c6e27Sflorian case LDNS_RDF_TYPE_TYPE: 1312ae8c6e27Sflorian return sldns_wire2str_type_scan(d, dlen, s, slen); 1313ae8c6e27Sflorian case LDNS_RDF_TYPE_CLASS: 1314ae8c6e27Sflorian return sldns_wire2str_class_scan(d, dlen, s, slen); 1315ae8c6e27Sflorian case LDNS_RDF_TYPE_CERT_ALG: 1316ae8c6e27Sflorian return sldns_wire2str_cert_alg_scan(d, dlen, s, slen); 1317ae8c6e27Sflorian case LDNS_RDF_TYPE_ALG: 1318ae8c6e27Sflorian return sldns_wire2str_alg_scan(d, dlen, s, slen); 1319ae8c6e27Sflorian case LDNS_RDF_TYPE_UNKNOWN: 1320ae8c6e27Sflorian return sldns_wire2str_unknown_scan(d, dlen, s, slen); 1321ae8c6e27Sflorian case LDNS_RDF_TYPE_TIME: 1322ae8c6e27Sflorian return sldns_wire2str_time_scan(d, dlen, s, slen); 1323ae8c6e27Sflorian case LDNS_RDF_TYPE_LOC: 1324ae8c6e27Sflorian return sldns_wire2str_loc_scan(d, dlen, s, slen); 1325ae8c6e27Sflorian case LDNS_RDF_TYPE_WKS: 1326ae8c6e27Sflorian case LDNS_RDF_TYPE_SERVICE: 1327ae8c6e27Sflorian return sldns_wire2str_wks_scan(d, dlen, s, slen); 1328ae8c6e27Sflorian case LDNS_RDF_TYPE_NSAP: 1329ae8c6e27Sflorian return sldns_wire2str_nsap_scan(d, dlen, s, slen); 1330ae8c6e27Sflorian case LDNS_RDF_TYPE_ATMA: 1331ae8c6e27Sflorian return sldns_wire2str_atma_scan(d, dlen, s, slen); 1332ae8c6e27Sflorian case LDNS_RDF_TYPE_IPSECKEY: 1333ae8c6e27Sflorian return sldns_wire2str_ipseckey_scan(d, dlen, s, slen, pkt, 133457403691Sflorian pktlen, comprloop); 1335ae8c6e27Sflorian case LDNS_RDF_TYPE_HIP: 1336ae8c6e27Sflorian return sldns_wire2str_hip_scan(d, dlen, s, slen); 1337ae8c6e27Sflorian case LDNS_RDF_TYPE_INT16_DATA: 1338ae8c6e27Sflorian return sldns_wire2str_int16_data_scan(d, dlen, s, slen); 1339ae8c6e27Sflorian case LDNS_RDF_TYPE_NSEC3_NEXT_OWNER: 1340ae8c6e27Sflorian return sldns_wire2str_b32_ext_scan(d, dlen, s, slen); 1341ae8c6e27Sflorian case LDNS_RDF_TYPE_ILNP64: 1342ae8c6e27Sflorian return sldns_wire2str_ilnp64_scan(d, dlen, s, slen); 1343ae8c6e27Sflorian case LDNS_RDF_TYPE_EUI48: 1344ae8c6e27Sflorian return sldns_wire2str_eui48_scan(d, dlen, s, slen); 1345ae8c6e27Sflorian case LDNS_RDF_TYPE_EUI64: 1346ae8c6e27Sflorian return sldns_wire2str_eui64_scan(d, dlen, s, slen); 1347ae8c6e27Sflorian case LDNS_RDF_TYPE_TAG: 1348ae8c6e27Sflorian return sldns_wire2str_tag_scan(d, dlen, s, slen); 1349ae8c6e27Sflorian case LDNS_RDF_TYPE_LONG_STR: 1350ae8c6e27Sflorian return sldns_wire2str_long_str_scan(d, dlen, s, slen); 1351411c5950Sflorian case LDNS_RDF_TYPE_SVCPARAM: 1352411c5950Sflorian return sldns_wire2str_svcparam_scan(d, dlen, s, slen); 1353ae8c6e27Sflorian case LDNS_RDF_TYPE_TSIGERROR: 1354ae8c6e27Sflorian return sldns_wire2str_tsigerror_scan(d, dlen, s, slen); 1355ae8c6e27Sflorian } 1356ae8c6e27Sflorian /* unknown rdf type */ 1357ae8c6e27Sflorian return -1; 1358ae8c6e27Sflorian } 1359ae8c6e27Sflorian 1360ae8c6e27Sflorian int sldns_wire2str_int8_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) 1361ae8c6e27Sflorian { 1362ae8c6e27Sflorian int w; 1363ae8c6e27Sflorian if(*dl < 1) return -1; 1364ae8c6e27Sflorian w = sldns_str_print(s, sl, "%u", (unsigned)**d); 1365ae8c6e27Sflorian (*d)++; 1366ae8c6e27Sflorian (*dl)--; 1367ae8c6e27Sflorian return w; 1368ae8c6e27Sflorian } 1369ae8c6e27Sflorian 1370ae8c6e27Sflorian int sldns_wire2str_int16_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) 1371ae8c6e27Sflorian { 1372ae8c6e27Sflorian int w; 1373ae8c6e27Sflorian if(*dl < 2) return -1; 1374ae8c6e27Sflorian w = sldns_str_print(s, sl, "%lu", (unsigned long)sldns_read_uint16(*d)); 1375ae8c6e27Sflorian (*d)+=2; 1376ae8c6e27Sflorian (*dl)-=2; 1377ae8c6e27Sflorian return w; 1378ae8c6e27Sflorian } 1379ae8c6e27Sflorian 1380ae8c6e27Sflorian int sldns_wire2str_int32_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) 1381ae8c6e27Sflorian { 1382ae8c6e27Sflorian int w; 1383ae8c6e27Sflorian if(*dl < 4) return -1; 1384ae8c6e27Sflorian w = sldns_str_print(s, sl, "%lu", (unsigned long)sldns_read_uint32(*d)); 1385ae8c6e27Sflorian (*d)+=4; 1386ae8c6e27Sflorian (*dl)-=4; 1387ae8c6e27Sflorian return w; 1388ae8c6e27Sflorian } 1389ae8c6e27Sflorian 1390ae8c6e27Sflorian int sldns_wire2str_period_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) 1391ae8c6e27Sflorian { 1392ae8c6e27Sflorian int w; 1393ae8c6e27Sflorian if(*dl < 4) return -1; 1394ae8c6e27Sflorian w = sldns_str_print(s, sl, "%u", (unsigned)sldns_read_uint32(*d)); 1395ae8c6e27Sflorian (*d)+=4; 1396ae8c6e27Sflorian (*dl)-=4; 1397ae8c6e27Sflorian return w; 1398ae8c6e27Sflorian } 1399ae8c6e27Sflorian 1400ae8c6e27Sflorian int sldns_wire2str_tsigtime_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) 1401ae8c6e27Sflorian { 1402ae8c6e27Sflorian /* tsigtime is 48 bits network order unsigned integer */ 1403ae8c6e27Sflorian int w; 1404ae8c6e27Sflorian uint64_t tsigtime = 0; 1405ae8c6e27Sflorian uint64_t d0, d1, d2, d3, d4, d5; 1406ae8c6e27Sflorian if(*dl < 6) return -1; 1407ae8c6e27Sflorian d0 = (*d)[0]; /* cast to uint64 for shift operations */ 1408ae8c6e27Sflorian d1 = (*d)[1]; 1409ae8c6e27Sflorian d2 = (*d)[2]; 1410ae8c6e27Sflorian d3 = (*d)[3]; 1411ae8c6e27Sflorian d4 = (*d)[4]; 1412ae8c6e27Sflorian d5 = (*d)[5]; 1413ae8c6e27Sflorian tsigtime = (d0<<40) | (d1<<32) | (d2<<24) | (d3<<16) | (d4<<8) | d5; 1414ae8c6e27Sflorian #ifndef USE_WINSOCK 1415ae8c6e27Sflorian w = sldns_str_print(s, sl, "%llu", (long long)tsigtime); 1416ae8c6e27Sflorian #else 1417ae8c6e27Sflorian w = sldns_str_print(s, sl, "%I64u", (long long)tsigtime); 1418ae8c6e27Sflorian #endif 1419ae8c6e27Sflorian (*d)+=6; 1420ae8c6e27Sflorian (*dl)-=6; 1421ae8c6e27Sflorian return w; 1422ae8c6e27Sflorian } 1423ae8c6e27Sflorian 1424ae8c6e27Sflorian int sldns_wire2str_a_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) 1425ae8c6e27Sflorian { 1426ae8c6e27Sflorian char buf[32]; 1427ae8c6e27Sflorian int w; 1428ae8c6e27Sflorian if(*dl < 4) return -1; 1429ae8c6e27Sflorian if(!inet_ntop(AF_INET, *d, buf, (socklen_t)sizeof(buf))) 1430ae8c6e27Sflorian return -1; 1431ae8c6e27Sflorian w = sldns_str_print(s, sl, "%s", buf); 1432ae8c6e27Sflorian (*d)+=4; 1433ae8c6e27Sflorian (*dl)-=4; 1434ae8c6e27Sflorian return w; 1435ae8c6e27Sflorian } 1436ae8c6e27Sflorian 1437ae8c6e27Sflorian int sldns_wire2str_aaaa_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) 1438ae8c6e27Sflorian { 1439ae8c6e27Sflorian #ifdef AF_INET6 1440ae8c6e27Sflorian char buf[64]; 1441ae8c6e27Sflorian int w; 1442ae8c6e27Sflorian if(*dl < 16) return -1; 1443ae8c6e27Sflorian if(!inet_ntop(AF_INET6, *d, buf, (socklen_t)sizeof(buf))) 1444ae8c6e27Sflorian return -1; 1445ae8c6e27Sflorian w = sldns_str_print(s, sl, "%s", buf); 1446ae8c6e27Sflorian (*d)+=16; 1447ae8c6e27Sflorian (*dl)-=16; 1448ae8c6e27Sflorian return w; 1449ae8c6e27Sflorian #else 1450ae8c6e27Sflorian return -1; 1451ae8c6e27Sflorian #endif 1452ae8c6e27Sflorian } 1453ae8c6e27Sflorian 1454ae8c6e27Sflorian /** printout escaped TYPE_STR character */ 1455ae8c6e27Sflorian static int str_char_print(char** s, size_t* sl, uint8_t c) 1456ae8c6e27Sflorian { 1457ae8c6e27Sflorian if(isprint((unsigned char)c) || c == '\t') { 1458ae8c6e27Sflorian if(c == '\"' || c == '\\') 1459ae8c6e27Sflorian return sldns_str_print(s, sl, "\\%c", c); 1460ae8c6e27Sflorian if(*sl) { 1461ae8c6e27Sflorian **s = (char)c; 1462ae8c6e27Sflorian (*s)++; 1463ae8c6e27Sflorian (*sl)--; 1464ae8c6e27Sflorian } 1465ae8c6e27Sflorian return 1; 1466ae8c6e27Sflorian } 1467ae8c6e27Sflorian return sldns_str_print(s, sl, "\\%03u", (unsigned)c); 1468ae8c6e27Sflorian } 1469ae8c6e27Sflorian 1470ae8c6e27Sflorian int sldns_wire2str_str_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) 1471ae8c6e27Sflorian { 1472ae8c6e27Sflorian int w = 0; 1473ae8c6e27Sflorian size_t i, len; 1474ae8c6e27Sflorian if(*dl < 1) return -1; 1475ae8c6e27Sflorian len = **d; 1476ae8c6e27Sflorian if(*dl < 1+len) return -1; 1477ae8c6e27Sflorian (*d)++; 1478ae8c6e27Sflorian (*dl)--; 1479ae8c6e27Sflorian w += sldns_str_print(s, sl, "\""); 1480ae8c6e27Sflorian for(i=0; i<len; i++) 1481ae8c6e27Sflorian w += str_char_print(s, sl, (*d)[i]); 1482ae8c6e27Sflorian w += sldns_str_print(s, sl, "\""); 1483ae8c6e27Sflorian (*d)+=len; 1484ae8c6e27Sflorian (*dl)-=len; 1485ae8c6e27Sflorian return w; 1486ae8c6e27Sflorian } 1487ae8c6e27Sflorian 1488ae8c6e27Sflorian int sldns_wire2str_apl_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) 1489ae8c6e27Sflorian { 1490ae8c6e27Sflorian int i, w = 0; 1491ae8c6e27Sflorian uint16_t family; 1492ae8c6e27Sflorian uint8_t negation, prefix, adflength; 1493ae8c6e27Sflorian if(*dl < 4) return -1; 1494ae8c6e27Sflorian family = sldns_read_uint16(*d); 1495ae8c6e27Sflorian prefix = (*d)[2]; 1496ae8c6e27Sflorian negation = ((*d)[3] & LDNS_APL_NEGATION); 1497ae8c6e27Sflorian adflength = ((*d)[3] & LDNS_APL_MASK); 1498ae8c6e27Sflorian if(*dl < 4+(size_t)adflength) return -1; 1499ae8c6e27Sflorian if(family != LDNS_APL_IP4 && family != LDNS_APL_IP6) 1500ae8c6e27Sflorian return -1; /* unknown address family */ 1501ae8c6e27Sflorian if(negation) 1502ae8c6e27Sflorian w += sldns_str_print(s, sl, "!"); 1503ae8c6e27Sflorian w += sldns_str_print(s, sl, "%u:", (unsigned)family); 1504ae8c6e27Sflorian if(family == LDNS_APL_IP4) { 1505ae8c6e27Sflorian /* check if prefix <32 ? */ 1506ae8c6e27Sflorian /* address is variable length 0 - 4 */ 1507ae8c6e27Sflorian for(i=0; i<4; i++) { 1508ae8c6e27Sflorian if(i > 0) 1509ae8c6e27Sflorian w += sldns_str_print(s, sl, "."); 1510ae8c6e27Sflorian if(i < (int)adflength) 1511ae8c6e27Sflorian w += sldns_str_print(s, sl, "%d", (*d)[4+i]); 1512ae8c6e27Sflorian else w += sldns_str_print(s, sl, "0"); 1513ae8c6e27Sflorian } 1514ae8c6e27Sflorian } else if(family == LDNS_APL_IP6) { 1515ae8c6e27Sflorian /* check if prefix <128 ? */ 1516ae8c6e27Sflorian /* address is variable length 0 - 16 */ 1517ae8c6e27Sflorian for(i=0; i<16; i++) { 1518ae8c6e27Sflorian if(i%2 == 0 && i>0) 1519ae8c6e27Sflorian w += sldns_str_print(s, sl, ":"); 1520ae8c6e27Sflorian if(i < (int)adflength) 1521ae8c6e27Sflorian w += sldns_str_print(s, sl, "%02x", (*d)[4+i]); 1522ae8c6e27Sflorian else w += sldns_str_print(s, sl, "00"); 1523ae8c6e27Sflorian } 1524ae8c6e27Sflorian } 1525ae8c6e27Sflorian w += sldns_str_print(s, sl, "/%u", (unsigned)prefix); 1526ae8c6e27Sflorian (*d) += 4+adflength; 1527ae8c6e27Sflorian (*dl) -= 4+adflength; 1528ae8c6e27Sflorian return w; 1529ae8c6e27Sflorian } 1530ae8c6e27Sflorian 1531ae8c6e27Sflorian int sldns_wire2str_b32_ext_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) 1532ae8c6e27Sflorian { 1533ae8c6e27Sflorian size_t datalen; 1534ae8c6e27Sflorian size_t sz; 1535ae8c6e27Sflorian if(*dl < 1) return -1; 1536ae8c6e27Sflorian datalen = (*d)[0]; 1537ae8c6e27Sflorian if(*dl < 1+datalen) return -1; 1538ae8c6e27Sflorian sz = sldns_b32_ntop_calculate_size(datalen); 1539ae8c6e27Sflorian if(*sl < sz+1) { 1540ae8c6e27Sflorian (*d) += datalen+1; 1541ae8c6e27Sflorian (*dl) -= (datalen+1); 1542ae8c6e27Sflorian return (int)sz; /* out of space really, but would need buffer 1543ae8c6e27Sflorian in order to truncate the output */ 1544ae8c6e27Sflorian } 1545ae8c6e27Sflorian sldns_b32_ntop_extended_hex((*d)+1, datalen, *s, *sl); 1546ae8c6e27Sflorian (*d) += datalen+1; 1547ae8c6e27Sflorian (*dl) -= (datalen+1); 1548ae8c6e27Sflorian (*s) += sz; 1549ae8c6e27Sflorian (*sl) -= sz; 1550ae8c6e27Sflorian return (int)sz; 1551ae8c6e27Sflorian } 1552ae8c6e27Sflorian 1553ae8c6e27Sflorian /** scan number of bytes from wire into b64 presentation format */ 1554ae8c6e27Sflorian static int sldns_wire2str_b64_scan_num(uint8_t** d, size_t* dl, char** s, 1555ae8c6e27Sflorian size_t* sl, size_t num) 1556ae8c6e27Sflorian { 1557ae8c6e27Sflorian /* b64_ntop_calculate size includes null at the end */ 1558ae8c6e27Sflorian size_t sz = sldns_b64_ntop_calculate_size(num)-1; 1559ae8c6e27Sflorian if(*sl < sz+1) { 1560ae8c6e27Sflorian (*d) += num; 1561ae8c6e27Sflorian (*dl) -= num; 1562ae8c6e27Sflorian return (int)sz; /* out of space really, but would need buffer 1563ae8c6e27Sflorian in order to truncate the output */ 1564ae8c6e27Sflorian } 1565ae8c6e27Sflorian sldns_b64_ntop(*d, num, *s, *sl); 1566ae8c6e27Sflorian (*d) += num; 1567ae8c6e27Sflorian (*dl) -= num; 1568ae8c6e27Sflorian (*s) += sz; 1569ae8c6e27Sflorian (*sl) -= sz; 1570ae8c6e27Sflorian return (int)sz; 1571ae8c6e27Sflorian } 1572ae8c6e27Sflorian 1573ae8c6e27Sflorian int sldns_wire2str_b64_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) 1574ae8c6e27Sflorian { 1575ae8c6e27Sflorian if(*dl == 0) { 1576ae8c6e27Sflorian return sldns_str_print(s, sl, "0"); 1577ae8c6e27Sflorian } 1578ae8c6e27Sflorian return sldns_wire2str_b64_scan_num(d, dl, s, sl, *dl); 1579ae8c6e27Sflorian } 1580ae8c6e27Sflorian 1581ae8c6e27Sflorian int sldns_wire2str_hex_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) 1582ae8c6e27Sflorian { 1583ae8c6e27Sflorian if(*dl == 0) { 1584ae8c6e27Sflorian return sldns_str_print(s, sl, "0"); 1585ae8c6e27Sflorian } 1586ae8c6e27Sflorian return print_remainder_hex("", d, dl, s, sl); 1587ae8c6e27Sflorian } 1588ae8c6e27Sflorian 1589ae8c6e27Sflorian int sldns_wire2str_nsec_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) 1590ae8c6e27Sflorian { 1591ae8c6e27Sflorian uint8_t* p = *d; 1592ae8c6e27Sflorian size_t pl = *dl; 1593ae8c6e27Sflorian unsigned i, bit, window, block_len; 1594ae8c6e27Sflorian uint16_t t; 1595ae8c6e27Sflorian int w = 0; 1596ae8c6e27Sflorian 1597ae8c6e27Sflorian /* check for errors */ 1598ae8c6e27Sflorian while(pl) { 1599ae8c6e27Sflorian if(pl < 2) return -1; 1600ae8c6e27Sflorian block_len = (unsigned)p[1]; 1601ae8c6e27Sflorian if(pl < 2+block_len) return -1; 1602ae8c6e27Sflorian p += block_len+2; 1603ae8c6e27Sflorian pl -= block_len+2; 1604ae8c6e27Sflorian } 1605ae8c6e27Sflorian 1606ae8c6e27Sflorian /* do it */ 1607ae8c6e27Sflorian p = *d; 1608ae8c6e27Sflorian pl = *dl; 1609ae8c6e27Sflorian while(pl) { 1610ae8c6e27Sflorian if(pl < 2) return -1; /* cannot happen */ 1611ae8c6e27Sflorian window = (unsigned)p[0]; 1612ae8c6e27Sflorian block_len = (unsigned)p[1]; 1613ae8c6e27Sflorian if(pl < 2+block_len) return -1; /* cannot happen */ 1614ae8c6e27Sflorian p += 2; 1615ae8c6e27Sflorian for(i=0; i<block_len; i++) { 1616ae8c6e27Sflorian if(p[i] == 0) continue; 1617ae8c6e27Sflorian /* base type number for this octet */ 1618ae8c6e27Sflorian t = ((window)<<8) | (i << 3); 1619ae8c6e27Sflorian for(bit=0; bit<8; bit++) { 1620ae8c6e27Sflorian if((p[i]&(0x80>>bit))) { 1621ae8c6e27Sflorian if(w) w += sldns_str_print(s, sl, " "); 1622ae8c6e27Sflorian w += sldns_wire2str_type_print(s, sl, 1623ae8c6e27Sflorian t+bit); 1624ae8c6e27Sflorian } 1625ae8c6e27Sflorian } 1626ae8c6e27Sflorian } 1627ae8c6e27Sflorian p += block_len; 1628ae8c6e27Sflorian pl -= block_len+2; 1629ae8c6e27Sflorian } 1630ae8c6e27Sflorian (*d) += *dl; 1631ae8c6e27Sflorian (*dl) = 0; 1632ae8c6e27Sflorian return w; 1633ae8c6e27Sflorian } 1634ae8c6e27Sflorian 1635ae8c6e27Sflorian int sldns_wire2str_nsec3_salt_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) 1636ae8c6e27Sflorian { 1637ae8c6e27Sflorian size_t salt_len; 1638ae8c6e27Sflorian int w; 1639ae8c6e27Sflorian if(*dl < 1) return -1; 1640ae8c6e27Sflorian salt_len = (size_t)(*d)[0]; 1641ae8c6e27Sflorian if(*dl < 1+salt_len) return -1; 1642ae8c6e27Sflorian (*d)++; 1643ae8c6e27Sflorian (*dl)--; 1644ae8c6e27Sflorian if(salt_len == 0) { 1645ae8c6e27Sflorian return sldns_str_print(s, sl, "-"); 1646ae8c6e27Sflorian } 1647ae8c6e27Sflorian w = print_hex_buf(s, sl, *d, salt_len); 1648ae8c6e27Sflorian (*dl)-=salt_len; 1649ae8c6e27Sflorian (*d)+=salt_len; 1650ae8c6e27Sflorian return w; 1651ae8c6e27Sflorian } 1652ae8c6e27Sflorian 1653ae8c6e27Sflorian int sldns_wire2str_cert_alg_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) 1654ae8c6e27Sflorian { 1655ae8c6e27Sflorian sldns_lookup_table *lt; 1656ae8c6e27Sflorian int data, w; 1657ae8c6e27Sflorian if(*dl < 2) return -1; 1658ae8c6e27Sflorian data = (int)sldns_read_uint16(*d); 1659ae8c6e27Sflorian lt = sldns_lookup_by_id(sldns_cert_algorithms, data); 1660ae8c6e27Sflorian if(lt && lt->name) 1661ae8c6e27Sflorian w = sldns_str_print(s, sl, "%s", lt->name); 1662ae8c6e27Sflorian else w = sldns_str_print(s, sl, "%d", data); 1663ae8c6e27Sflorian (*dl)-=2; 1664ae8c6e27Sflorian (*d)+=2; 1665ae8c6e27Sflorian return w; 1666ae8c6e27Sflorian } 1667ae8c6e27Sflorian 1668ae8c6e27Sflorian int sldns_wire2str_alg_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) 1669ae8c6e27Sflorian { 1670ae8c6e27Sflorian /* don't use algorithm mnemonics in the presentation format 1671ae8c6e27Sflorian * this kind of got sneaked into the rfc's */ 1672ae8c6e27Sflorian return sldns_wire2str_int8_scan(d, dl, s, sl); 1673ae8c6e27Sflorian } 1674ae8c6e27Sflorian 1675ae8c6e27Sflorian int sldns_wire2str_unknown_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) 1676ae8c6e27Sflorian { 1677ae8c6e27Sflorian return sldns_wire2str_rdata_unknown_scan(d, dl, s, sl); 1678ae8c6e27Sflorian } 1679ae8c6e27Sflorian 1680ae8c6e27Sflorian int sldns_wire2str_time_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) 1681ae8c6e27Sflorian { 1682ae8c6e27Sflorian /* create a YYYYMMDDHHMMSS string if possible */ 1683ae8c6e27Sflorian struct tm tm; 1684ae8c6e27Sflorian char date_buf[16]; 1685ae8c6e27Sflorian uint32_t t; 1686ae8c6e27Sflorian memset(&tm, 0, sizeof(tm)); 1687ae8c6e27Sflorian if(*dl < 4) return -1; 1688ae8c6e27Sflorian t = sldns_read_uint32(*d); 1689ae8c6e27Sflorian date_buf[15]=0; 1690ae8c6e27Sflorian if(sldns_serial_arithmetics_gmtime_r(t, time(NULL), &tm) && 1691ae8c6e27Sflorian strftime(date_buf, 15, "%Y%m%d%H%M%S", &tm)) { 1692ae8c6e27Sflorian (*d) += 4; 1693ae8c6e27Sflorian (*dl) -= 4; 1694ae8c6e27Sflorian return sldns_str_print(s, sl, "%s", date_buf); 1695ae8c6e27Sflorian } 1696ae8c6e27Sflorian return -1; 1697ae8c6e27Sflorian } 1698ae8c6e27Sflorian 1699ae8c6e27Sflorian static int 1700ae8c6e27Sflorian loc_cm_print(char** str, size_t* sl, uint8_t mantissa, uint8_t exponent) 1701ae8c6e27Sflorian { 1702ae8c6e27Sflorian int w = 0; 1703ae8c6e27Sflorian uint8_t i; 1704ae8c6e27Sflorian /* is it 0.<two digits> ? */ 1705ae8c6e27Sflorian if(exponent < 2) { 1706ae8c6e27Sflorian if(exponent == 1) 1707ae8c6e27Sflorian mantissa *= 10; 1708ae8c6e27Sflorian return sldns_str_print(str, sl, "0.%02ld", (long)mantissa); 1709ae8c6e27Sflorian } 1710ae8c6e27Sflorian /* always <digit><string of zeros> */ 1711ae8c6e27Sflorian w += sldns_str_print(str, sl, "%d", (int)mantissa); 1712ae8c6e27Sflorian for(i=0; i<exponent-2; i++) 1713ae8c6e27Sflorian w += sldns_str_print(str, sl, "0"); 1714ae8c6e27Sflorian return w; 1715ae8c6e27Sflorian } 1716ae8c6e27Sflorian 1717ae8c6e27Sflorian int sldns_wire2str_loc_scan(uint8_t** d, size_t* dl, char** str, size_t* sl) 1718ae8c6e27Sflorian { 1719ae8c6e27Sflorian /* we could do checking (ie degrees < 90 etc)? */ 1720ae8c6e27Sflorian uint8_t version; 1721ae8c6e27Sflorian uint8_t size; 1722ae8c6e27Sflorian uint8_t horizontal_precision; 1723ae8c6e27Sflorian uint8_t vertical_precision; 1724ae8c6e27Sflorian uint32_t longitude; 1725ae8c6e27Sflorian uint32_t latitude; 1726ae8c6e27Sflorian uint32_t altitude; 1727ae8c6e27Sflorian char northerness; 1728ae8c6e27Sflorian char easterness; 1729ae8c6e27Sflorian uint32_t h; 1730ae8c6e27Sflorian uint32_t m; 1731ae8c6e27Sflorian double s; 1732ae8c6e27Sflorian uint32_t equator = (uint32_t)1 << 31; /* 2**31 */ 1733ae8c6e27Sflorian int w = 0; 1734ae8c6e27Sflorian 1735ae8c6e27Sflorian if(*dl < 16) return -1; 1736ae8c6e27Sflorian version = (*d)[0]; 1737ae8c6e27Sflorian if(version != 0) 1738ae8c6e27Sflorian return sldns_wire2str_hex_scan(d, dl, str, sl); 1739ae8c6e27Sflorian size = (*d)[1]; 1740ae8c6e27Sflorian horizontal_precision = (*d)[2]; 1741ae8c6e27Sflorian vertical_precision = (*d)[3]; 1742ae8c6e27Sflorian 1743ae8c6e27Sflorian latitude = sldns_read_uint32((*d)+4); 1744ae8c6e27Sflorian longitude = sldns_read_uint32((*d)+8); 1745ae8c6e27Sflorian altitude = sldns_read_uint32((*d)+12); 1746ae8c6e27Sflorian 1747ae8c6e27Sflorian if (latitude > equator) { 1748ae8c6e27Sflorian northerness = 'N'; 1749ae8c6e27Sflorian latitude = latitude - equator; 1750ae8c6e27Sflorian } else { 1751ae8c6e27Sflorian northerness = 'S'; 1752ae8c6e27Sflorian latitude = equator - latitude; 1753ae8c6e27Sflorian } 1754ae8c6e27Sflorian h = latitude / (1000 * 60 * 60); 1755ae8c6e27Sflorian latitude = latitude % (1000 * 60 * 60); 1756ae8c6e27Sflorian m = latitude / (1000 * 60); 1757ae8c6e27Sflorian latitude = latitude % (1000 * 60); 1758ae8c6e27Sflorian s = (double) latitude / 1000.0; 1759ae8c6e27Sflorian w += sldns_str_print(str, sl, "%02u %02u %06.3f %c ", 1760ae8c6e27Sflorian h, m, s, northerness); 1761ae8c6e27Sflorian 1762ae8c6e27Sflorian if (longitude > equator) { 1763ae8c6e27Sflorian easterness = 'E'; 1764ae8c6e27Sflorian longitude = longitude - equator; 1765ae8c6e27Sflorian } else { 1766ae8c6e27Sflorian easterness = 'W'; 1767ae8c6e27Sflorian longitude = equator - longitude; 1768ae8c6e27Sflorian } 1769ae8c6e27Sflorian h = longitude / (1000 * 60 * 60); 1770ae8c6e27Sflorian longitude = longitude % (1000 * 60 * 60); 1771ae8c6e27Sflorian m = longitude / (1000 * 60); 1772ae8c6e27Sflorian longitude = longitude % (1000 * 60); 1773ae8c6e27Sflorian s = (double) longitude / (1000.0); 1774ae8c6e27Sflorian w += sldns_str_print(str, sl, "%02u %02u %06.3f %c ", 1775ae8c6e27Sflorian h, m, s, easterness); 1776ae8c6e27Sflorian 1777ae8c6e27Sflorian s = ((double) altitude) / 100; 1778ae8c6e27Sflorian s -= 100000; 1779ae8c6e27Sflorian 1780ae8c6e27Sflorian if(altitude%100 != 0) 1781ae8c6e27Sflorian w += sldns_str_print(str, sl, "%.2f", s); 1782ae8c6e27Sflorian else 1783ae8c6e27Sflorian w += sldns_str_print(str, sl, "%.0f", s); 1784ae8c6e27Sflorian 1785ae8c6e27Sflorian w += sldns_str_print(str, sl, "m "); 1786ae8c6e27Sflorian 1787ae8c6e27Sflorian w += loc_cm_print(str, sl, (size & 0xf0) >> 4, size & 0x0f); 1788ae8c6e27Sflorian w += sldns_str_print(str, sl, "m "); 1789ae8c6e27Sflorian 1790ae8c6e27Sflorian w += loc_cm_print(str, sl, (horizontal_precision & 0xf0) >> 4, 1791ae8c6e27Sflorian horizontal_precision & 0x0f); 1792ae8c6e27Sflorian w += sldns_str_print(str, sl, "m "); 1793ae8c6e27Sflorian 1794ae8c6e27Sflorian w += loc_cm_print(str, sl, (vertical_precision & 0xf0) >> 4, 1795ae8c6e27Sflorian vertical_precision & 0x0f); 1796ae8c6e27Sflorian w += sldns_str_print(str, sl, "m"); 1797ae8c6e27Sflorian 1798ae8c6e27Sflorian (*d)+=16; 1799ae8c6e27Sflorian (*dl)-=16; 1800ae8c6e27Sflorian return w; 1801ae8c6e27Sflorian } 1802ae8c6e27Sflorian 1803ae8c6e27Sflorian int sldns_wire2str_wks_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) 1804ae8c6e27Sflorian { 1805ae8c6e27Sflorian /* protocol, followed by bitmap of services */ 1806ae8c6e27Sflorian const char* proto_name = NULL; 1807ae8c6e27Sflorian struct protoent *protocol; 1808ae8c6e27Sflorian struct servent *service; 1809ae8c6e27Sflorian uint8_t protocol_nr; 1810ae8c6e27Sflorian int bit, port, w = 0; 1811ae8c6e27Sflorian size_t i; 1812ae8c6e27Sflorian /* we cannot print with strings because they 1813ae8c6e27Sflorian * are not portable, the presentation format may 1814ae8c6e27Sflorian * not be able to be read in on another computer. */ 1815ae8c6e27Sflorian int print_symbols = 0; 1816ae8c6e27Sflorian 1817ae8c6e27Sflorian /* protocol */ 1818ae8c6e27Sflorian if(*dl < 1) return -1; 1819ae8c6e27Sflorian protocol_nr = (*d)[0]; 1820ae8c6e27Sflorian (*d)++; 1821ae8c6e27Sflorian (*dl)--; 1822ae8c6e27Sflorian protocol = getprotobynumber((int)protocol_nr); 1823ae8c6e27Sflorian if(protocol && (protocol->p_name != NULL)) { 1824ae8c6e27Sflorian w += sldns_str_print(s, sl, "%s", protocol->p_name); 1825ae8c6e27Sflorian proto_name = protocol->p_name; 1826ae8c6e27Sflorian } else if(protocol_nr == 6) { 1827ae8c6e27Sflorian w += sldns_str_print(s, sl, "tcp"); 1828ae8c6e27Sflorian } else if(protocol_nr == 17) { 1829ae8c6e27Sflorian w += sldns_str_print(s, sl, "udp"); 1830ae8c6e27Sflorian } else { 1831ae8c6e27Sflorian w += sldns_str_print(s, sl, "%u", (unsigned)protocol_nr); 1832ae8c6e27Sflorian } 1833ae8c6e27Sflorian 1834ae8c6e27Sflorian for(i=0; i<*dl; i++) { 1835ae8c6e27Sflorian if((*d)[i] == 0) 1836ae8c6e27Sflorian continue; 1837ae8c6e27Sflorian for(bit=0; bit<8; bit++) { 1838ae8c6e27Sflorian if(!(((*d)[i])&(0x80>>bit))) 1839ae8c6e27Sflorian continue; 1840ae8c6e27Sflorian port = (int)i*8 + bit; 1841ae8c6e27Sflorian 1842ae8c6e27Sflorian if(!print_symbols) 1843ae8c6e27Sflorian service = NULL; 1844ae8c6e27Sflorian else 1845ae8c6e27Sflorian service = getservbyport( 1846ae8c6e27Sflorian (int)htons((uint16_t)port), proto_name); 1847ae8c6e27Sflorian if(service && service->s_name) 1848ae8c6e27Sflorian w += sldns_str_print(s, sl, " %s", 1849ae8c6e27Sflorian service->s_name); 1850ae8c6e27Sflorian else w += sldns_str_print(s, sl, " %u", 1851ae8c6e27Sflorian (unsigned)port); 1852ae8c6e27Sflorian } 1853ae8c6e27Sflorian } 1854ae8c6e27Sflorian 1855ae8c6e27Sflorian #ifdef HAVE_ENDSERVENT 1856ae8c6e27Sflorian endservent(); 1857ae8c6e27Sflorian #endif 1858ae8c6e27Sflorian #ifdef HAVE_ENDPROTOENT 1859ae8c6e27Sflorian endprotoent(); 1860ae8c6e27Sflorian #endif 1861ae8c6e27Sflorian (*d) += *dl; 1862ae8c6e27Sflorian (*dl) = 0; 1863ae8c6e27Sflorian return w; 1864ae8c6e27Sflorian } 1865ae8c6e27Sflorian 1866ae8c6e27Sflorian int sldns_wire2str_nsap_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) 1867ae8c6e27Sflorian { 1868ae8c6e27Sflorian return print_remainder_hex("0x", d, dl, s, sl); 1869ae8c6e27Sflorian } 1870ae8c6e27Sflorian 1871ae8c6e27Sflorian int sldns_wire2str_atma_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) 1872ae8c6e27Sflorian { 1873ae8c6e27Sflorian return print_remainder_hex("", d, dl, s, sl); 1874ae8c6e27Sflorian } 1875ae8c6e27Sflorian 1876ae8c6e27Sflorian /* internal scan routine that can modify arguments on failure */ 1877ae8c6e27Sflorian static int sldns_wire2str_ipseckey_scan_internal(uint8_t** d, size_t* dl, 187857403691Sflorian char** s, size_t* sl, uint8_t* pkt, size_t pktlen, int* comprloop) 1879ae8c6e27Sflorian { 1880ae8c6e27Sflorian /* http://www.ietf.org/internet-drafts/draft-ietf-ipseckey-rr-12.txt*/ 1881ae8c6e27Sflorian uint8_t precedence, gateway_type, algorithm; 1882ae8c6e27Sflorian int w = 0; 1883ae8c6e27Sflorian 1884ae8c6e27Sflorian if(*dl < 3) return -1; 1885ae8c6e27Sflorian precedence = (*d)[0]; 1886ae8c6e27Sflorian gateway_type = (*d)[1]; 1887ae8c6e27Sflorian algorithm = (*d)[2]; 1888ae8c6e27Sflorian if(gateway_type > 3) 1889ae8c6e27Sflorian return -1; /* unknown */ 1890ae8c6e27Sflorian (*d)+=3; 1891ae8c6e27Sflorian (*dl)-=3; 1892ae8c6e27Sflorian w += sldns_str_print(s, sl, "%d %d %d ", 1893ae8c6e27Sflorian (int)precedence, (int)gateway_type, (int)algorithm); 1894ae8c6e27Sflorian 1895ae8c6e27Sflorian switch(gateway_type) { 1896ae8c6e27Sflorian case 0: /* no gateway */ 1897ae8c6e27Sflorian w += sldns_str_print(s, sl, "."); 1898ae8c6e27Sflorian break; 1899ae8c6e27Sflorian case 1: /* ip4 */ 1900ae8c6e27Sflorian w += sldns_wire2str_a_scan(d, dl, s, sl); 1901ae8c6e27Sflorian break; 1902ae8c6e27Sflorian case 2: /* ip6 */ 1903ae8c6e27Sflorian w += sldns_wire2str_aaaa_scan(d, dl, s, sl); 1904ae8c6e27Sflorian break; 1905ae8c6e27Sflorian case 3: /* dname */ 190657403691Sflorian w += sldns_wire2str_dname_scan(d, dl, s, sl, pkt, pktlen, comprloop); 1907ae8c6e27Sflorian break; 1908ae8c6e27Sflorian default: /* unknown */ 1909ae8c6e27Sflorian return -1; 1910ae8c6e27Sflorian } 1911ae8c6e27Sflorian 1912ae8c6e27Sflorian if(*dl < 1) 1913ae8c6e27Sflorian return -1; 1914ae8c6e27Sflorian w += sldns_str_print(s, sl, " "); 1915ae8c6e27Sflorian w += sldns_wire2str_b64_scan_num(d, dl, s, sl, *dl); 1916ae8c6e27Sflorian return w; 1917ae8c6e27Sflorian } 1918ae8c6e27Sflorian 1919ae8c6e27Sflorian int sldns_wire2str_ipseckey_scan(uint8_t** d, size_t* dl, char** s, size_t* sl, 192057403691Sflorian uint8_t* pkt, size_t pktlen, int* comprloop) 1921ae8c6e27Sflorian { 1922ae8c6e27Sflorian uint8_t* od = *d; 1923ae8c6e27Sflorian char* os = *s; 1924ae8c6e27Sflorian size_t odl = *dl, osl = *sl; 192557403691Sflorian int w=sldns_wire2str_ipseckey_scan_internal(d, dl, s, sl, pkt, pktlen, comprloop); 1926ae8c6e27Sflorian if(w == -1) { 1927ae8c6e27Sflorian *d = od; 1928ae8c6e27Sflorian *s = os; 1929ae8c6e27Sflorian *dl = odl; 1930ae8c6e27Sflorian *sl = osl; 1931ae8c6e27Sflorian return -1; 1932ae8c6e27Sflorian } 1933ae8c6e27Sflorian return w; 1934ae8c6e27Sflorian } 1935ae8c6e27Sflorian 1936ae8c6e27Sflorian int sldns_wire2str_hip_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) 1937ae8c6e27Sflorian { 1938ae8c6e27Sflorian int w; 1939ae8c6e27Sflorian uint8_t algo, hitlen; 1940ae8c6e27Sflorian uint16_t pklen; 1941ae8c6e27Sflorian 1942ae8c6e27Sflorian /* read lengths */ 1943ae8c6e27Sflorian if(*dl < 4) 1944ae8c6e27Sflorian return -1; 1945ae8c6e27Sflorian hitlen = (*d)[0]; 1946ae8c6e27Sflorian algo = (*d)[1]; 1947ae8c6e27Sflorian pklen = sldns_read_uint16((*d)+2); 1948ae8c6e27Sflorian if(*dl < (size_t)4 + (size_t)hitlen + (size_t)pklen) 1949ae8c6e27Sflorian return -1; 1950ae8c6e27Sflorian 1951ae8c6e27Sflorian /* write: algo hit pubkey */ 1952ae8c6e27Sflorian w = sldns_str_print(s, sl, "%u ", (unsigned)algo); 1953ae8c6e27Sflorian w += print_hex_buf(s, sl, (*d)+4, hitlen); 1954ae8c6e27Sflorian w += sldns_str_print(s, sl, " "); 1955ae8c6e27Sflorian (*d)+=4+hitlen; 1956ae8c6e27Sflorian (*dl)-= (4+hitlen); 1957ae8c6e27Sflorian w += sldns_wire2str_b64_scan_num(d, dl, s, sl, pklen); 1958ae8c6e27Sflorian return w; 1959ae8c6e27Sflorian } 1960ae8c6e27Sflorian 1961ae8c6e27Sflorian int sldns_wire2str_int16_data_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) 1962ae8c6e27Sflorian { 1963ae8c6e27Sflorian int w; 1964ae8c6e27Sflorian uint16_t n; 1965ae8c6e27Sflorian if(*dl < 2) 1966ae8c6e27Sflorian return -1; 1967ae8c6e27Sflorian n = sldns_read_uint16(*d); 1968ae8c6e27Sflorian if(*dl < 2+(size_t)n) 1969ae8c6e27Sflorian return -1; 1970ae8c6e27Sflorian (*d)+=2; 1971ae8c6e27Sflorian (*dl)-=2; 1972ae8c6e27Sflorian if(n == 0) { 1973ae8c6e27Sflorian return sldns_str_print(s, sl, "0"); 1974ae8c6e27Sflorian } 1975ae8c6e27Sflorian w = sldns_str_print(s, sl, "%u ", (unsigned)n); 1976ae8c6e27Sflorian w += sldns_wire2str_b64_scan_num(d, dl, s, sl, n); 1977ae8c6e27Sflorian return w; 1978ae8c6e27Sflorian } 1979ae8c6e27Sflorian 1980ae8c6e27Sflorian int sldns_wire2str_nsec3_next_owner_scan(uint8_t** d, size_t* dl, char** s, 1981ae8c6e27Sflorian size_t* sl) 1982ae8c6e27Sflorian { 1983ae8c6e27Sflorian return sldns_wire2str_b32_ext_scan(d, dl, s, sl); 1984ae8c6e27Sflorian } 1985ae8c6e27Sflorian 1986ae8c6e27Sflorian int sldns_wire2str_ilnp64_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) 1987ae8c6e27Sflorian { 1988ae8c6e27Sflorian int w; 1989ae8c6e27Sflorian if(*dl < 8) 1990ae8c6e27Sflorian return -1; 1991ae8c6e27Sflorian w = sldns_str_print(s, sl, "%.4x:%.4x:%.4x:%.4x", 1992ae8c6e27Sflorian sldns_read_uint16(*d), sldns_read_uint16((*d)+2), 1993ae8c6e27Sflorian sldns_read_uint16((*d)+4), sldns_read_uint16((*d)+6)); 1994ae8c6e27Sflorian (*d)+=8; 1995ae8c6e27Sflorian (*dl)-=8; 1996ae8c6e27Sflorian return w; 1997ae8c6e27Sflorian } 1998ae8c6e27Sflorian 1999ae8c6e27Sflorian int sldns_wire2str_eui48_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) 2000ae8c6e27Sflorian { 2001ae8c6e27Sflorian int w; 2002ae8c6e27Sflorian if(*dl < 6) 2003ae8c6e27Sflorian return -1; 2004ae8c6e27Sflorian w = sldns_str_print(s, sl, "%.2x-%.2x-%.2x-%.2x-%.2x-%.2x", 2005ae8c6e27Sflorian (*d)[0], (*d)[1], (*d)[2], (*d)[3], (*d)[4], (*d)[5]); 2006ae8c6e27Sflorian (*d)+=6; 2007ae8c6e27Sflorian (*dl)-=6; 2008ae8c6e27Sflorian return w; 2009ae8c6e27Sflorian } 2010ae8c6e27Sflorian 2011ae8c6e27Sflorian int sldns_wire2str_eui64_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) 2012ae8c6e27Sflorian { 2013ae8c6e27Sflorian int w; 2014ae8c6e27Sflorian if(*dl < 8) 2015ae8c6e27Sflorian return -1; 2016ae8c6e27Sflorian w = sldns_str_print(s, sl, "%.2x-%.2x-%.2x-%.2x-%.2x-%.2x-%.2x-%.2x", 2017ae8c6e27Sflorian (*d)[0], (*d)[1], (*d)[2], (*d)[3], (*d)[4], (*d)[5], 2018ae8c6e27Sflorian (*d)[6], (*d)[7]); 2019ae8c6e27Sflorian (*d)+=8; 2020ae8c6e27Sflorian (*dl)-=8; 2021ae8c6e27Sflorian return w; 2022ae8c6e27Sflorian } 2023ae8c6e27Sflorian 2024ae8c6e27Sflorian int sldns_wire2str_tag_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) 2025ae8c6e27Sflorian { 2026ae8c6e27Sflorian size_t i, n; 2027ae8c6e27Sflorian int w = 0; 2028ae8c6e27Sflorian if(*dl < 1) 2029ae8c6e27Sflorian return -1; 2030ae8c6e27Sflorian n = (size_t)((*d)[0]); 2031ae8c6e27Sflorian if(*dl < 1+n) 2032ae8c6e27Sflorian return -1; 2033ae8c6e27Sflorian for(i=0; i<n; i++) 2034ae8c6e27Sflorian if(!isalnum((unsigned char)(*d)[i+1])) 2035ae8c6e27Sflorian return -1; 2036ae8c6e27Sflorian for(i=0; i<n; i++) 2037ae8c6e27Sflorian w += sldns_str_print(s, sl, "%c", (char)(*d)[i+1]); 2038ae8c6e27Sflorian (*d)+=n+1; 2039ae8c6e27Sflorian (*dl)-=(n+1); 2040ae8c6e27Sflorian return w; 2041ae8c6e27Sflorian } 2042ae8c6e27Sflorian 2043ae8c6e27Sflorian int sldns_wire2str_long_str_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) 2044ae8c6e27Sflorian { 2045ae8c6e27Sflorian size_t i; 2046ae8c6e27Sflorian int w = 0; 2047ae8c6e27Sflorian w += sldns_str_print(s, sl, "\""); 2048ae8c6e27Sflorian for(i=0; i<*dl; i++) 2049ae8c6e27Sflorian w += str_char_print(s, sl, (*d)[i]); 2050ae8c6e27Sflorian w += sldns_str_print(s, sl, "\""); 2051ae8c6e27Sflorian (*d)+=*dl; 2052ae8c6e27Sflorian (*dl)=0; 2053ae8c6e27Sflorian return w; 2054ae8c6e27Sflorian } 2055ae8c6e27Sflorian 2056ae8c6e27Sflorian int sldns_wire2str_tsigerror_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) 2057ae8c6e27Sflorian { 2058ae8c6e27Sflorian sldns_lookup_table *lt; 2059ae8c6e27Sflorian int data, w; 2060ae8c6e27Sflorian if(*dl < 2) return -1; 2061ae8c6e27Sflorian data = (int)sldns_read_uint16(*d); 2062ae8c6e27Sflorian lt = sldns_lookup_by_id(sldns_tsig_errors, data); 2063ae8c6e27Sflorian if(lt && lt->name) 2064ae8c6e27Sflorian w = sldns_str_print(s, sl, "%s", lt->name); 2065ae8c6e27Sflorian else w = sldns_str_print(s, sl, "%d", data); 2066ae8c6e27Sflorian (*dl)-=2; 2067ae8c6e27Sflorian (*d)+=2; 2068ae8c6e27Sflorian return w; 2069ae8c6e27Sflorian } 2070ae8c6e27Sflorian 2071ae8c6e27Sflorian int sldns_wire2str_edns_llq_print(char** s, size_t* sl, uint8_t* data, 2072ae8c6e27Sflorian size_t len) 2073ae8c6e27Sflorian { 2074ae8c6e27Sflorian /* LLQ constants */ 2075ae8c6e27Sflorian const char* llq_errors[] = {"NO-ERROR", "SERV-FULL", "STATIC", 2076ae8c6e27Sflorian "FORMAT-ERR", "NO-SUCH-LLQ", "BAD-VERS", "UNKNOWN_ERR"}; 2077ae8c6e27Sflorian const unsigned int llq_errors_num = 7; 2078ae8c6e27Sflorian const char* llq_opcodes[] = {"LLQ-SETUP", "LLQ-REFRESH", "LLQ-EVENT"}; 2079ae8c6e27Sflorian const unsigned int llq_opcodes_num = 3; 2080ae8c6e27Sflorian uint16_t version, llq_opcode, error_code; 2081ae8c6e27Sflorian uint64_t llq_id; 2082ae8c6e27Sflorian uint32_t lease_life; /* Requested or granted life of LLQ, in seconds */ 2083ae8c6e27Sflorian int w = 0; 2084ae8c6e27Sflorian 2085ae8c6e27Sflorian /* read the record */ 2086ae8c6e27Sflorian if(len != 18) { 2087ae8c6e27Sflorian w += sldns_str_print(s, sl, "malformed LLQ "); 2088ae8c6e27Sflorian w += print_hex_buf(s, sl, data, len); 2089ae8c6e27Sflorian return w; 2090ae8c6e27Sflorian } 2091ae8c6e27Sflorian version = sldns_read_uint16(data); 2092ae8c6e27Sflorian llq_opcode = sldns_read_uint16(data+2); 2093ae8c6e27Sflorian error_code = sldns_read_uint16(data+4); 2094ae8c6e27Sflorian memmove(&llq_id, data+6, sizeof(llq_id)); 2095ae8c6e27Sflorian lease_life = sldns_read_uint32(data+14); 2096ae8c6e27Sflorian 2097ae8c6e27Sflorian /* print it */ 2098ae8c6e27Sflorian w += sldns_str_print(s, sl, "v%d ", (int)version); 2099ae8c6e27Sflorian if(llq_opcode < llq_opcodes_num) 2100ae8c6e27Sflorian w += sldns_str_print(s, sl, "%s", llq_opcodes[llq_opcode]); 2101ae8c6e27Sflorian else w += sldns_str_print(s, sl, "opcode %d", (int)llq_opcode); 2102ae8c6e27Sflorian if(error_code < llq_errors_num) 2103ae8c6e27Sflorian w += sldns_str_print(s, sl, " %s", llq_errors[error_code]); 2104ae8c6e27Sflorian else w += sldns_str_print(s, sl, " error %d", (int)error_code); 2105ae8c6e27Sflorian #ifndef USE_WINSOCK 2106ae8c6e27Sflorian w += sldns_str_print(s, sl, " id %llx lease-life %lu", 2107ae8c6e27Sflorian (unsigned long long)llq_id, (unsigned long)lease_life); 2108ae8c6e27Sflorian #else 2109ae8c6e27Sflorian w += sldns_str_print(s, sl, " id %I64x lease-life %lu", 2110ae8c6e27Sflorian (unsigned long long)llq_id, (unsigned long)lease_life); 2111ae8c6e27Sflorian #endif 2112ae8c6e27Sflorian return w; 2113ae8c6e27Sflorian } 2114ae8c6e27Sflorian 2115ae8c6e27Sflorian int sldns_wire2str_edns_ul_print(char** s, size_t* sl, uint8_t* data, 2116ae8c6e27Sflorian size_t len) 2117ae8c6e27Sflorian { 2118ae8c6e27Sflorian uint32_t lease; 2119ae8c6e27Sflorian int w = 0; 2120ae8c6e27Sflorian if(len != 4) { 2121ae8c6e27Sflorian w += sldns_str_print(s, sl, "malformed UL "); 2122ae8c6e27Sflorian w += print_hex_buf(s, sl, data, len); 2123ae8c6e27Sflorian return w; 2124ae8c6e27Sflorian } 2125ae8c6e27Sflorian lease = sldns_read_uint32(data); 2126ae8c6e27Sflorian w += sldns_str_print(s, sl, "lease %lu", (unsigned long)lease); 2127ae8c6e27Sflorian return w; 2128ae8c6e27Sflorian } 2129ae8c6e27Sflorian 2130ae8c6e27Sflorian int sldns_wire2str_edns_nsid_print(char** s, size_t* sl, uint8_t* data, 2131ae8c6e27Sflorian size_t len) 2132ae8c6e27Sflorian { 2133ae8c6e27Sflorian int w = 0; 2134ae8c6e27Sflorian size_t i, printed=0; 2135ae8c6e27Sflorian w += print_hex_buf(s, sl, data, len); 2136ae8c6e27Sflorian for(i=0; i<len; i++) { 2137ae8c6e27Sflorian if(isprint((unsigned char)data[i]) || data[i] == '\t') { 2138ae8c6e27Sflorian if(!printed) { 2139ae8c6e27Sflorian w += sldns_str_print(s, sl, " ("); 2140ae8c6e27Sflorian printed = 1; 2141ae8c6e27Sflorian } 2142ae8c6e27Sflorian w += sldns_str_print(s, sl, "%c", (char)data[i]); 2143ae8c6e27Sflorian } 2144ae8c6e27Sflorian } 2145ae8c6e27Sflorian if(printed) 2146ae8c6e27Sflorian w += sldns_str_print(s, sl, ")"); 2147ae8c6e27Sflorian return w; 2148ae8c6e27Sflorian } 2149ae8c6e27Sflorian 2150ae8c6e27Sflorian int sldns_wire2str_edns_dau_print(char** s, size_t* sl, uint8_t* data, 2151ae8c6e27Sflorian size_t len) 2152ae8c6e27Sflorian { 2153ae8c6e27Sflorian sldns_lookup_table *lt; 2154ae8c6e27Sflorian size_t i; 2155ae8c6e27Sflorian int w = 0; 2156ae8c6e27Sflorian for(i=0; i<len; i++) { 2157ae8c6e27Sflorian lt = sldns_lookup_by_id(sldns_algorithms, (int)data[i]); 2158ae8c6e27Sflorian if(lt && lt->name) 2159ae8c6e27Sflorian w += sldns_str_print(s, sl, " %s", lt->name); 2160ae8c6e27Sflorian else w += sldns_str_print(s, sl, " %d", (int)data[i]); 2161ae8c6e27Sflorian } 2162ae8c6e27Sflorian return w; 2163ae8c6e27Sflorian } 2164ae8c6e27Sflorian 2165ae8c6e27Sflorian int sldns_wire2str_edns_dhu_print(char** s, size_t* sl, uint8_t* data, 2166ae8c6e27Sflorian size_t len) 2167ae8c6e27Sflorian { 2168ae8c6e27Sflorian sldns_lookup_table *lt; 2169ae8c6e27Sflorian size_t i; 2170ae8c6e27Sflorian int w = 0; 2171ae8c6e27Sflorian for(i=0; i<len; i++) { 2172ae8c6e27Sflorian lt = sldns_lookup_by_id(sldns_hashes, (int)data[i]); 2173ae8c6e27Sflorian if(lt && lt->name) 2174ae8c6e27Sflorian w += sldns_str_print(s, sl, " %s", lt->name); 2175ae8c6e27Sflorian else w += sldns_str_print(s, sl, " %d", (int)data[i]); 2176ae8c6e27Sflorian } 2177ae8c6e27Sflorian return w; 2178ae8c6e27Sflorian } 2179ae8c6e27Sflorian 2180ae8c6e27Sflorian int sldns_wire2str_edns_n3u_print(char** s, size_t* sl, uint8_t* data, 2181ae8c6e27Sflorian size_t len) 2182ae8c6e27Sflorian { 2183ae8c6e27Sflorian size_t i; 2184ae8c6e27Sflorian int w = 0; 2185ae8c6e27Sflorian for(i=0; i<len; i++) { 2186ae8c6e27Sflorian if(data[i] == 1) 2187ae8c6e27Sflorian w += sldns_str_print(s, sl, " SHA1"); 2188ae8c6e27Sflorian else w += sldns_str_print(s, sl, " %d", (int)data[i]); 2189ae8c6e27Sflorian } 2190ae8c6e27Sflorian return w; 2191ae8c6e27Sflorian } 2192ae8c6e27Sflorian 2193ae8c6e27Sflorian int sldns_wire2str_edns_subnet_print(char** s, size_t* sl, uint8_t* data, 2194ae8c6e27Sflorian size_t len) 2195ae8c6e27Sflorian { 2196ae8c6e27Sflorian int w = 0; 2197ae8c6e27Sflorian uint16_t family; 2198ae8c6e27Sflorian uint8_t source, scope; 2199ae8c6e27Sflorian if(len < 4) { 2200ae8c6e27Sflorian w += sldns_str_print(s, sl, "malformed subnet "); 2201ae8c6e27Sflorian w += print_hex_buf(s, sl, data, len); 2202ae8c6e27Sflorian return w; 2203ae8c6e27Sflorian } 2204ae8c6e27Sflorian family = sldns_read_uint16(data); 2205ae8c6e27Sflorian source = data[2]; 2206ae8c6e27Sflorian scope = data[3]; 2207ae8c6e27Sflorian if(family == 1) { 2208ae8c6e27Sflorian /* IP4 */ 2209ae8c6e27Sflorian char buf[64]; 2210ae8c6e27Sflorian uint8_t ip4[4]; 2211ae8c6e27Sflorian memset(ip4, 0, sizeof(ip4)); 2212ae8c6e27Sflorian if(len-4 > 4) { 2213ae8c6e27Sflorian w += sldns_str_print(s, sl, "trailingdata:"); 2214ae8c6e27Sflorian w += print_hex_buf(s, sl, data+4+4, len-4-4); 2215ae8c6e27Sflorian w += sldns_str_print(s, sl, " "); 2216ae8c6e27Sflorian len = 4+4; 2217ae8c6e27Sflorian } 2218ae8c6e27Sflorian memmove(ip4, data+4, len-4); 2219ae8c6e27Sflorian if(!inet_ntop(AF_INET, ip4, buf, (socklen_t)sizeof(buf))) { 2220ae8c6e27Sflorian w += sldns_str_print(s, sl, "ip4ntoperror "); 2221ae8c6e27Sflorian w += print_hex_buf(s, sl, data+4+4, len-4-4); 2222ae8c6e27Sflorian } else { 2223ae8c6e27Sflorian w += sldns_str_print(s, sl, "%s", buf); 2224ae8c6e27Sflorian } 2225ae8c6e27Sflorian } else if(family == 2) { 2226ae8c6e27Sflorian /* IP6 */ 2227ae8c6e27Sflorian char buf[64]; 2228ae8c6e27Sflorian uint8_t ip6[16]; 2229ae8c6e27Sflorian memset(ip6, 0, sizeof(ip6)); 2230ae8c6e27Sflorian if(len-4 > 16) { 2231ae8c6e27Sflorian w += sldns_str_print(s, sl, "trailingdata:"); 2232ae8c6e27Sflorian w += print_hex_buf(s, sl, data+4+16, len-4-16); 2233ae8c6e27Sflorian w += sldns_str_print(s, sl, " "); 2234ae8c6e27Sflorian len = 4+16; 2235ae8c6e27Sflorian } 2236ae8c6e27Sflorian memmove(ip6, data+4, len-4); 2237ae8c6e27Sflorian #ifdef AF_INET6 2238ae8c6e27Sflorian if(!inet_ntop(AF_INET6, ip6, buf, (socklen_t)sizeof(buf))) { 2239ae8c6e27Sflorian w += sldns_str_print(s, sl, "ip6ntoperror "); 2240ae8c6e27Sflorian w += print_hex_buf(s, sl, data+4+4, len-4-4); 2241ae8c6e27Sflorian } else { 2242ae8c6e27Sflorian w += sldns_str_print(s, sl, "%s", buf); 2243ae8c6e27Sflorian } 2244ae8c6e27Sflorian #else 2245ae8c6e27Sflorian w += print_hex_buf(s, sl, data+4+4, len-4-4); 2246ae8c6e27Sflorian #endif 2247ae8c6e27Sflorian } else { 2248ae8c6e27Sflorian /* unknown */ 2249ae8c6e27Sflorian w += sldns_str_print(s, sl, "family %d ", 2250ae8c6e27Sflorian (int)family); 2251ae8c6e27Sflorian w += print_hex_buf(s, sl, data, len); 2252ae8c6e27Sflorian } 2253ae8c6e27Sflorian w += sldns_str_print(s, sl, "/%d scope /%d", (int)source, (int)scope); 2254ae8c6e27Sflorian return w; 2255ae8c6e27Sflorian } 2256ae8c6e27Sflorian 22577a211805Sflorian static int sldns_wire2str_edns_keepalive_print(char** s, size_t* sl, 22587a211805Sflorian uint8_t* data, size_t len) 2259ae8c6e27Sflorian { 2260ae8c6e27Sflorian int w = 0; 2261ae8c6e27Sflorian uint16_t timeout; 2262ae8c6e27Sflorian if(!(len == 0 || len == 2)) { 2263ae8c6e27Sflorian w += sldns_str_print(s, sl, "malformed keepalive "); 2264ae8c6e27Sflorian w += print_hex_buf(s, sl, data, len); 2265ae8c6e27Sflorian return w; 2266ae8c6e27Sflorian } 2267ae8c6e27Sflorian if(len == 0 ) { 2268ae8c6e27Sflorian w += sldns_str_print(s, sl, "no timeout value (only valid for client option) "); 2269ae8c6e27Sflorian } else { 2270ae8c6e27Sflorian timeout = sldns_read_uint16(data); 2271ae8c6e27Sflorian w += sldns_str_print(s, sl, "timeout value in units of 100ms %u", (int)timeout); 2272ae8c6e27Sflorian } 2273ae8c6e27Sflorian return w; 2274ae8c6e27Sflorian } 2275ae8c6e27Sflorian 227654cc57acSflorian int sldns_wire2str_edns_ede_print(char** s, size_t* sl, 227754cc57acSflorian uint8_t* data, size_t len) 227854cc57acSflorian { 227954cc57acSflorian uint16_t ede_code; 228054cc57acSflorian int w = 0; 228154cc57acSflorian sldns_lookup_table *lt; 228254cc57acSflorian size_t i; 228354cc57acSflorian int printable; 228454cc57acSflorian 228554cc57acSflorian if(len < 2) { 228654cc57acSflorian w += sldns_str_print(s, sl, "malformed ede "); 228754cc57acSflorian w += print_hex_buf(s, sl, data, len); 228854cc57acSflorian return w; 228954cc57acSflorian } 229054cc57acSflorian 229154cc57acSflorian ede_code = sldns_read_uint16(data); 229254cc57acSflorian lt = sldns_lookup_by_id(sldns_edns_ede_codes, (int)ede_code); 229354cc57acSflorian if(lt && lt->name) 229454cc57acSflorian w += sldns_str_print(s, sl, "%s", lt->name); 229554cc57acSflorian else w += sldns_str_print(s, sl, "%d", (int)ede_code); 229654cc57acSflorian 229754cc57acSflorian if(len == 2) 229854cc57acSflorian return w; 229954cc57acSflorian 230054cc57acSflorian w += sldns_str_print(s, sl, " "); 230154cc57acSflorian 230254cc57acSflorian /* If it looks like text, show it as text. */ 230354cc57acSflorian printable=1; 230454cc57acSflorian for(i=2; i<len; i++) { 230554cc57acSflorian if(isprint((unsigned char)data[i]) || data[i] == '\t') 230654cc57acSflorian continue; 230754cc57acSflorian printable = 0; 230854cc57acSflorian break; 230954cc57acSflorian } 231054cc57acSflorian if(printable) { 231154cc57acSflorian w += sldns_str_print(s, sl, "\""); 231254cc57acSflorian for(i=2; i<len; i++) { 231354cc57acSflorian w += str_char_print(s, sl, data[i]); 231454cc57acSflorian } 231554cc57acSflorian w += sldns_str_print(s, sl, "\""); 231654cc57acSflorian } else { 231754cc57acSflorian w += print_hex_buf(s, sl, data+2, len-2); 231854cc57acSflorian } 231954cc57acSflorian return w; 232054cc57acSflorian } 232154cc57acSflorian 2322ae8c6e27Sflorian int sldns_wire2str_edns_option_print(char** s, size_t* sl, 2323ae8c6e27Sflorian uint16_t option_code, uint8_t* optdata, size_t optlen) 2324ae8c6e27Sflorian { 2325ae8c6e27Sflorian int w = 0; 2326ae8c6e27Sflorian w += sldns_wire2str_edns_option_code_print(s, sl, option_code); 2327ae8c6e27Sflorian w += sldns_str_print(s, sl, ": "); 2328ae8c6e27Sflorian switch(option_code) { 2329ae8c6e27Sflorian case LDNS_EDNS_LLQ: 2330ae8c6e27Sflorian w += sldns_wire2str_edns_llq_print(s, sl, optdata, optlen); 2331ae8c6e27Sflorian break; 2332ae8c6e27Sflorian case LDNS_EDNS_UL: 2333ae8c6e27Sflorian w += sldns_wire2str_edns_ul_print(s, sl, optdata, optlen); 2334ae8c6e27Sflorian break; 2335ae8c6e27Sflorian case LDNS_EDNS_NSID: 2336ae8c6e27Sflorian w += sldns_wire2str_edns_nsid_print(s, sl, optdata, optlen); 2337ae8c6e27Sflorian break; 2338ae8c6e27Sflorian case LDNS_EDNS_DAU: 2339ae8c6e27Sflorian w += sldns_wire2str_edns_dau_print(s, sl, optdata, optlen); 2340ae8c6e27Sflorian break; 2341ae8c6e27Sflorian case LDNS_EDNS_DHU: 2342ae8c6e27Sflorian w += sldns_wire2str_edns_dhu_print(s, sl, optdata, optlen); 2343ae8c6e27Sflorian break; 2344ae8c6e27Sflorian case LDNS_EDNS_N3U: 2345ae8c6e27Sflorian w += sldns_wire2str_edns_n3u_print(s, sl, optdata, optlen); 2346ae8c6e27Sflorian break; 2347ae8c6e27Sflorian case LDNS_EDNS_CLIENT_SUBNET: 2348ae8c6e27Sflorian w += sldns_wire2str_edns_subnet_print(s, sl, optdata, optlen); 2349ae8c6e27Sflorian break; 2350ae8c6e27Sflorian case LDNS_EDNS_KEEPALIVE: 2351ae8c6e27Sflorian w += sldns_wire2str_edns_keepalive_print(s, sl, optdata, optlen); 2352ae8c6e27Sflorian break; 2353ae8c6e27Sflorian case LDNS_EDNS_PADDING: 2354ae8c6e27Sflorian w += print_hex_buf(s, sl, optdata, optlen); 2355ae8c6e27Sflorian break; 235654cc57acSflorian case LDNS_EDNS_EDE: 235754cc57acSflorian w += sldns_wire2str_edns_ede_print(s, sl, optdata, optlen); 235854cc57acSflorian break; 2359ae8c6e27Sflorian default: 2360ae8c6e27Sflorian /* unknown option code */ 2361ae8c6e27Sflorian w += print_hex_buf(s, sl, optdata, optlen); 2362ae8c6e27Sflorian break; 2363ae8c6e27Sflorian } 2364ae8c6e27Sflorian return w; 2365ae8c6e27Sflorian } 2366ae8c6e27Sflorian 2367ae8c6e27Sflorian /** print the edns options to string */ 2368ae8c6e27Sflorian static int 2369ae8c6e27Sflorian print_edns_opts(char** s, size_t* sl, uint8_t* rdata, size_t rdatalen) 2370ae8c6e27Sflorian { 2371ae8c6e27Sflorian uint16_t option_code, option_len; 2372ae8c6e27Sflorian int w = 0; 2373ae8c6e27Sflorian while(rdatalen > 0) { 2374ae8c6e27Sflorian /* option name */ 2375ae8c6e27Sflorian if(rdatalen < 4) { 2376ae8c6e27Sflorian w += sldns_str_print(s, sl, " ; malformed: "); 2377ae8c6e27Sflorian w += print_hex_buf(s, sl, rdata, rdatalen); 2378ae8c6e27Sflorian return w; 2379ae8c6e27Sflorian } 2380ae8c6e27Sflorian option_code = sldns_read_uint16(rdata); 2381ae8c6e27Sflorian option_len = sldns_read_uint16(rdata+2); 2382ae8c6e27Sflorian rdata += 4; 2383ae8c6e27Sflorian rdatalen -= 4; 2384ae8c6e27Sflorian 2385ae8c6e27Sflorian /* option value */ 2386ae8c6e27Sflorian if(rdatalen < (size_t)option_len) { 2387ae8c6e27Sflorian w += sldns_str_print(s, sl, " ; malformed "); 2388ae8c6e27Sflorian w += sldns_wire2str_edns_option_code_print(s, sl, 2389ae8c6e27Sflorian option_code); 2390ae8c6e27Sflorian w += sldns_str_print(s, sl, ": "); 2391ae8c6e27Sflorian w += print_hex_buf(s, sl, rdata, rdatalen); 2392ae8c6e27Sflorian return w; 2393ae8c6e27Sflorian } 2394ae8c6e27Sflorian w += sldns_str_print(s, sl, " ; "); 2395ae8c6e27Sflorian w += sldns_wire2str_edns_option_print(s, sl, option_code, 2396ae8c6e27Sflorian rdata, option_len); 2397ae8c6e27Sflorian rdata += option_len; 2398ae8c6e27Sflorian rdatalen -= option_len; 2399ae8c6e27Sflorian } 2400ae8c6e27Sflorian return w; 2401ae8c6e27Sflorian } 2402ae8c6e27Sflorian 2403ae8c6e27Sflorian int sldns_wire2str_edns_scan(uint8_t** data, size_t* data_len, char** str, 2404ae8c6e27Sflorian size_t* str_len, uint8_t* pkt, size_t pktlen) 2405ae8c6e27Sflorian { 2406ae8c6e27Sflorian int w = 0; 2407ae8c6e27Sflorian uint8_t ext_rcode, edns_version; 2408ae8c6e27Sflorian uint16_t udpsize, edns_bits, rdatalen; 2409ae8c6e27Sflorian w += sldns_str_print(str, str_len, "; EDNS:"); 2410ae8c6e27Sflorian 2411ae8c6e27Sflorian /* some input checks, domain name */ 2412ae8c6e27Sflorian if(*data_len < 1+10) 2413ae8c6e27Sflorian return w + print_remainder_hex("Error malformed 0x", 2414ae8c6e27Sflorian data, data_len, str, str_len); 2415ae8c6e27Sflorian if(*data[0] != 0) { 2416ae8c6e27Sflorian return w + print_remainder_hex("Error nonrootdname 0x", 2417ae8c6e27Sflorian data, data_len, str, str_len); 2418ae8c6e27Sflorian } 2419ae8c6e27Sflorian (*data)++; 2420ae8c6e27Sflorian (*data_len)--; 2421ae8c6e27Sflorian 2422ae8c6e27Sflorian /* check type and read fixed contents */ 2423ae8c6e27Sflorian if(sldns_read_uint16((*data)) != LDNS_RR_TYPE_OPT) { 2424ae8c6e27Sflorian return w + print_remainder_hex("Error nottypeOPT 0x", 2425ae8c6e27Sflorian data, data_len, str, str_len); 2426ae8c6e27Sflorian } 2427ae8c6e27Sflorian udpsize = sldns_read_uint16((*data)+2); 2428ae8c6e27Sflorian ext_rcode = (*data)[4]; 2429ae8c6e27Sflorian edns_version = (*data)[5]; 2430ae8c6e27Sflorian edns_bits = sldns_read_uint16((*data)+6); 2431ae8c6e27Sflorian rdatalen = sldns_read_uint16((*data)+8); 2432ae8c6e27Sflorian (*data)+=10; 2433ae8c6e27Sflorian (*data_len)-=10; 2434ae8c6e27Sflorian 2435ae8c6e27Sflorian w += sldns_str_print(str, str_len, " version: %u;", 2436ae8c6e27Sflorian (unsigned)edns_version); 2437ae8c6e27Sflorian w += sldns_str_print(str, str_len, " flags:"); 2438ae8c6e27Sflorian if((edns_bits & LDNS_EDNS_MASK_DO_BIT)) 2439ae8c6e27Sflorian w += sldns_str_print(str, str_len, " do"); 2440ae8c6e27Sflorian /* the extended rcode is the value set, shifted four bits, 2441ae8c6e27Sflorian * and or'd with the original rcode */ 2442ae8c6e27Sflorian if(ext_rcode) { 2443ae8c6e27Sflorian int rc = ((int)ext_rcode)<<4; 2444ae8c6e27Sflorian if(pkt && pktlen >= LDNS_HEADER_SIZE) 2445ae8c6e27Sflorian rc |= LDNS_RCODE_WIRE(pkt); 2446ae8c6e27Sflorian w += sldns_str_print(str, str_len, " ; ext-rcode: %d", rc); 2447ae8c6e27Sflorian } 2448ae8c6e27Sflorian w += sldns_str_print(str, str_len, " ; udp: %u", (unsigned)udpsize); 2449ae8c6e27Sflorian 2450ae8c6e27Sflorian if(rdatalen) { 2451ae8c6e27Sflorian if((size_t)*data_len < rdatalen) { 2452ae8c6e27Sflorian w += sldns_str_print(str, str_len, 2453ae8c6e27Sflorian " ; Error EDNS rdata too short; "); 2454ae8c6e27Sflorian rdatalen = (uint16_t)*data_len; 2455ae8c6e27Sflorian } 2456ae8c6e27Sflorian w += print_edns_opts(str, str_len, *data, rdatalen); 2457ae8c6e27Sflorian (*data) += rdatalen; 2458ae8c6e27Sflorian (*data_len) -= rdatalen; 2459ae8c6e27Sflorian } 2460ae8c6e27Sflorian w += sldns_str_print(str, str_len, "\n"); 2461ae8c6e27Sflorian return w; 2462ae8c6e27Sflorian } 2463