wire2str.c revision 266077
1266077Sdes/* 2266077Sdes * wire2str.c 3266077Sdes * 4266077Sdes * conversion routines from the wire format 5266077Sdes * to the presentation format (strings) 6266077Sdes * 7266077Sdes * (c) NLnet Labs, 2004-2006 8266077Sdes * 9266077Sdes * See the file LICENSE for the license 10266077Sdes */ 11266077Sdes/** 12266077Sdes * \file 13266077Sdes * 14266077Sdes * Contains functions to translate the wireformat to text 15266077Sdes * representation, as well as functions to print them. 16266077Sdes */ 17266077Sdes#include "config.h" 18266077Sdes#include "ldns/wire2str.h" 19266077Sdes#include "ldns/str2wire.h" 20266077Sdes#include "ldns/rrdef.h" 21266077Sdes#include "ldns/pkthdr.h" 22266077Sdes#include "ldns/parseutil.h" 23266077Sdes#include "ldns/sbuffer.h" 24266077Sdes#include "ldns/keyraw.h" 25266077Sdes#ifdef HAVE_TIME_H 26266077Sdes#include <time.h> 27266077Sdes#endif 28266077Sdes#include <sys/time.h> 29266077Sdes#include <stdarg.h> 30266077Sdes#include <ctype.h> 31266077Sdes#ifdef HAVE_NETDB_H 32266077Sdes#include <netdb.h> 33266077Sdes#endif 34266077Sdes 35266077Sdes/* lookup tables for standard DNS stuff */ 36266077Sdes/* Taken from RFC 2535, section 7. */ 37266077Sdesstatic sldns_lookup_table sldns_algorithms_data[] = { 38266077Sdes { LDNS_RSAMD5, "RSAMD5" }, 39266077Sdes { LDNS_DH, "DH" }, 40266077Sdes { LDNS_DSA, "DSA" }, 41266077Sdes { LDNS_ECC, "ECC" }, 42266077Sdes { LDNS_RSASHA1, "RSASHA1" }, 43266077Sdes { LDNS_DSA_NSEC3, "DSA-NSEC3-SHA1" }, 44266077Sdes { LDNS_RSASHA1_NSEC3, "RSASHA1-NSEC3-SHA1" }, 45266077Sdes { LDNS_RSASHA256, "RSASHA256"}, 46266077Sdes { LDNS_RSASHA512, "RSASHA512"}, 47266077Sdes { LDNS_ECC_GOST, "ECC-GOST"}, 48266077Sdes { LDNS_ECDSAP256SHA256, "ECDSAP256SHA256"}, 49266077Sdes { LDNS_ECDSAP384SHA384, "ECDSAP384SHA384"}, 50266077Sdes { LDNS_INDIRECT, "INDIRECT" }, 51266077Sdes { LDNS_PRIVATEDNS, "PRIVATEDNS" }, 52266077Sdes { LDNS_PRIVATEOID, "PRIVATEOID" }, 53266077Sdes { 0, NULL } 54266077Sdes}; 55266077Sdessldns_lookup_table* sldns_algorithms = sldns_algorithms_data; 56266077Sdes 57266077Sdes/* hash algorithms in DS record */ 58266077Sdesstatic sldns_lookup_table sldns_hashes_data[] = { 59266077Sdes { LDNS_SHA1, "SHA1" }, 60266077Sdes { LDNS_SHA256, "SHA256" }, 61266077Sdes { LDNS_HASH_GOST, "HASH-GOST" }, 62266077Sdes { LDNS_SHA384, "SHA384" }, 63266077Sdes { 0, NULL } 64266077Sdes}; 65266077Sdessldns_lookup_table* sldns_hashes = sldns_hashes_data; 66266077Sdes 67266077Sdes/* Taken from RFC 4398 */ 68266077Sdesstatic sldns_lookup_table sldns_cert_algorithms_data[] = { 69266077Sdes { LDNS_CERT_PKIX, "PKIX" }, 70266077Sdes { LDNS_CERT_SPKI, "SPKI" }, 71266077Sdes { LDNS_CERT_PGP, "PGP" }, 72266077Sdes { LDNS_CERT_IPKIX, "IPKIX" }, 73266077Sdes { LDNS_CERT_ISPKI, "ISPKI" }, 74266077Sdes { LDNS_CERT_IPGP, "IPGP" }, 75266077Sdes { LDNS_CERT_ACPKIX, "ACPKIX" }, 76266077Sdes { LDNS_CERT_IACPKIX, "IACPKIX" }, 77266077Sdes { LDNS_CERT_URI, "URI" }, 78266077Sdes { LDNS_CERT_OID, "OID" }, 79266077Sdes { 0, NULL } 80266077Sdes}; 81266077Sdessldns_lookup_table* sldns_cert_algorithms = sldns_cert_algorithms_data; 82266077Sdes 83266077Sdes/* if these are used elsewhere */ 84266077Sdesstatic sldns_lookup_table sldns_rcodes_data[] = { 85266077Sdes { LDNS_RCODE_NOERROR, "NOERROR" }, 86266077Sdes { LDNS_RCODE_FORMERR, "FORMERR" }, 87266077Sdes { LDNS_RCODE_SERVFAIL, "SERVFAIL" }, 88266077Sdes { LDNS_RCODE_NXDOMAIN, "NXDOMAIN" }, 89266077Sdes { LDNS_RCODE_NOTIMPL, "NOTIMPL" }, 90266077Sdes { LDNS_RCODE_REFUSED, "REFUSED" }, 91266077Sdes { LDNS_RCODE_YXDOMAIN, "YXDOMAIN" }, 92266077Sdes { LDNS_RCODE_YXRRSET, "YXRRSET" }, 93266077Sdes { LDNS_RCODE_NXRRSET, "NXRRSET" }, 94266077Sdes { LDNS_RCODE_NOTAUTH, "NOTAUTH" }, 95266077Sdes { LDNS_RCODE_NOTZONE, "NOTZONE" }, 96266077Sdes { 0, NULL } 97266077Sdes}; 98266077Sdessldns_lookup_table* sldns_rcodes = sldns_rcodes_data; 99266077Sdes 100266077Sdesstatic sldns_lookup_table sldns_opcodes_data[] = { 101266077Sdes { LDNS_PACKET_QUERY, "QUERY" }, 102266077Sdes { LDNS_PACKET_IQUERY, "IQUERY" }, 103266077Sdes { LDNS_PACKET_STATUS, "STATUS" }, 104266077Sdes { LDNS_PACKET_NOTIFY, "NOTIFY" }, 105266077Sdes { LDNS_PACKET_UPDATE, "UPDATE" }, 106266077Sdes { 0, NULL } 107266077Sdes}; 108266077Sdessldns_lookup_table* sldns_opcodes = sldns_opcodes_data; 109266077Sdes 110266077Sdesstatic sldns_lookup_table sldns_wireparse_errors_data[] = { 111266077Sdes { LDNS_WIREPARSE_ERR_OK, "no parse error" }, 112266077Sdes { LDNS_WIREPARSE_ERR_GENERAL, "parse error" }, 113266077Sdes { LDNS_WIREPARSE_ERR_DOMAINNAME_OVERFLOW, "Domainname length overflow" }, 114266077Sdes { LDNS_WIREPARSE_ERR_DOMAINNAME_UNDERFLOW, "Domainname length underflow (zero length)" }, 115266077Sdes { LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, "buffer too small" }, 116266077Sdes { LDNS_WIREPARSE_ERR_LABEL_OVERFLOW, "Label length overflow" }, 117266077Sdes { LDNS_WIREPARSE_ERR_EMPTY_LABEL, "Empty label" }, 118266077Sdes { LDNS_WIREPARSE_ERR_SYNTAX_BAD_ESCAPE, "Syntax error, bad escape sequence" }, 119266077Sdes { LDNS_WIREPARSE_ERR_SYNTAX, "Syntax error, could not parse the RR" }, 120266077Sdes { LDNS_WIREPARSE_ERR_SYNTAX_TTL, "Syntax error, could not parse the RR's TTL" }, 121266077Sdes { LDNS_WIREPARSE_ERR_SYNTAX_TYPE, "Syntax error, could not parse the RR's type" }, 122266077Sdes { LDNS_WIREPARSE_ERR_SYNTAX_CLASS, "Syntax error, could not parse the RR's class" }, 123266077Sdes { LDNS_WIREPARSE_ERR_SYNTAX_RDATA, "Syntax error, could not parse the RR's rdata" }, 124266077Sdes { LDNS_WIREPARSE_ERR_SYNTAX_MISSING_VALUE, "Syntax error, value expected" }, 125266077Sdes { LDNS_WIREPARSE_ERR_INVALID_STR, "Conversion error, string expected" }, 126266077Sdes { LDNS_WIREPARSE_ERR_SYNTAX_B64, "Conversion error, b64 encoding expected" }, 127266077Sdes { LDNS_WIREPARSE_ERR_SYNTAX_B32_EXT, "Conversion error, b32 ext encoding expected" }, 128266077Sdes { LDNS_WIREPARSE_ERR_SYNTAX_HEX, "Conversion error, hex encoding expected" }, 129266077Sdes { LDNS_WIREPARSE_ERR_CERT_BAD_ALGORITHM, "Bad algorithm type for CERT record" }, 130266077Sdes { LDNS_WIREPARSE_ERR_SYNTAX_TIME, "Conversion error, time encoding expected" }, 131266077Sdes { LDNS_WIREPARSE_ERR_SYNTAX_PERIOD, "Conversion error, time period encoding expected" }, 132266077Sdes { LDNS_WIREPARSE_ERR_SYNTAX_ILNP64, "Conversion error, 4 colon separated hex numbers expected" }, 133266077Sdes { LDNS_WIREPARSE_ERR_SYNTAX_EUI48, 134266077Sdes "Conversion error, 6 two character hex numbers " 135266077Sdes "separated by dashes expected (i.e. xx-xx-xx-xx-xx-xx" }, 136266077Sdes { LDNS_WIREPARSE_ERR_SYNTAX_EUI64, 137266077Sdes "Conversion error, 8 two character hex numbers " 138266077Sdes "separated by dashes expected (i.e. xx-xx-xx-xx-xx-xx-xx-xx" }, 139266077Sdes { LDNS_WIREPARSE_ERR_SYNTAX_TAG, 140266077Sdes "Conversion error, a non-zero sequence of US-ASCII letters " 141266077Sdes "and numbers in lower case expected" }, 142266077Sdes { LDNS_WIREPARSE_ERR_NOT_IMPL, "not implemented" }, 143266077Sdes { LDNS_WIREPARSE_ERR_SYNTAX_INT, "Conversion error, integer expected" }, 144266077Sdes { LDNS_WIREPARSE_ERR_SYNTAX_IP4, "Conversion error, ip4 addr expected" }, 145266077Sdes { LDNS_WIREPARSE_ERR_SYNTAX_IP6, "Conversion error, ip6 addr expected" }, 146266077Sdes { LDNS_WIREPARSE_ERR_SYNTAX_INTEGER_OVERFLOW, "Syntax error, integer overflow" }, 147266077Sdes { LDNS_WIREPARSE_ERR_INCLUDE, "$INCLUDE directive was seen in the zone" }, 148266077Sdes { LDNS_WIREPARSE_ERR_PARENTHESIS, "Parse error, parenthesis mismatch" }, 149266077Sdes { 0, NULL } 150266077Sdes}; 151266077Sdessldns_lookup_table* sldns_wireparse_errors = sldns_wireparse_errors_data; 152266077Sdes 153266077Sdesstatic sldns_lookup_table sldns_edns_flags_data[] = { 154266077Sdes { 3600, "do"}, 155266077Sdes { 0, NULL} 156266077Sdes}; 157266077Sdessldns_lookup_table* sldns_edns_flags = sldns_edns_flags_data; 158266077Sdes 159266077Sdesstatic sldns_lookup_table sldns_edns_options_data[] = { 160266077Sdes { 1, "LLQ" }, 161266077Sdes { 2, "UL" }, 162266077Sdes { 3, "NSID" }, 163266077Sdes /* 4 draft-cheshire-edns0-owner-option */ 164266077Sdes { 5, "DAU" }, 165266077Sdes { 6, "DHU" }, 166266077Sdes { 7, "N3U" }, 167266077Sdes { 8, "edns-client-subnet" }, 168266077Sdes { 0, NULL} 169266077Sdes}; 170266077Sdessldns_lookup_table* sldns_edns_options = sldns_edns_options_data; 171266077Sdes 172266077Sdeschar* sldns_wire2str_pkt(uint8_t* data, size_t len) 173266077Sdes{ 174266077Sdes size_t slen = (size_t)sldns_wire2str_pkt_buf(data, len, NULL, 0); 175266077Sdes char* result = (char*)malloc(slen+1); 176266077Sdes if(!result) return NULL; 177266077Sdes sldns_wire2str_pkt_buf(data, len, result, slen+1); 178266077Sdes return result; 179266077Sdes} 180266077Sdes 181266077Sdeschar* sldns_wire2str_rr(uint8_t* rr, size_t len) 182266077Sdes{ 183266077Sdes size_t slen = (size_t)sldns_wire2str_rr_buf(rr, len, NULL, 0); 184266077Sdes char* result = (char*)malloc(slen+1); 185266077Sdes if(!result) return NULL; 186266077Sdes sldns_wire2str_rr_buf(rr, len, result, slen+1); 187266077Sdes return result; 188266077Sdes} 189266077Sdes 190266077Sdeschar* sldns_wire2str_type(uint16_t rrtype) 191266077Sdes{ 192266077Sdes char buf[16]; 193266077Sdes sldns_wire2str_type_buf(rrtype, buf, sizeof(buf)); 194266077Sdes return strdup(buf); 195266077Sdes} 196266077Sdes 197266077Sdeschar* sldns_wire2str_class(uint16_t rrclass) 198266077Sdes{ 199266077Sdes char buf[16]; 200266077Sdes sldns_wire2str_class_buf(rrclass, buf, sizeof(buf)); 201266077Sdes return strdup(buf); 202266077Sdes} 203266077Sdes 204266077Sdeschar* sldns_wire2str_dname(uint8_t* dname, size_t dname_len) 205266077Sdes{ 206266077Sdes size_t slen=(size_t)sldns_wire2str_dname_buf(dname, dname_len, NULL, 0); 207266077Sdes char* result = (char*)malloc(slen+1); 208266077Sdes if(!result) return NULL; 209266077Sdes sldns_wire2str_dname_buf(dname, dname_len, result, slen+1); 210266077Sdes return result; 211266077Sdes} 212266077Sdes 213266077Sdeschar* sldns_wire2str_rcode(int rcode) 214266077Sdes{ 215266077Sdes char buf[16]; 216266077Sdes sldns_wire2str_rcode_buf(rcode, buf, sizeof(buf)); 217266077Sdes return strdup(buf); 218266077Sdes} 219266077Sdes 220266077Sdesint sldns_wire2str_pkt_buf(uint8_t* d, size_t dlen, char* s, size_t slen) 221266077Sdes{ 222266077Sdes /* use arguments as temporary variables */ 223266077Sdes return sldns_wire2str_pkt_scan(&d, &dlen, &s, &slen); 224266077Sdes} 225266077Sdes 226266077Sdesint sldns_wire2str_rr_buf(uint8_t* d, size_t dlen, char* s, size_t slen) 227266077Sdes{ 228266077Sdes /* use arguments as temporary variables */ 229266077Sdes return sldns_wire2str_rr_scan(&d, &dlen, &s, &slen, NULL, 0); 230266077Sdes} 231266077Sdes 232266077Sdesint sldns_wire2str_rdata_buf(uint8_t* rdata, size_t rdata_len, char* str, 233266077Sdes size_t str_len, uint16_t rrtype) 234266077Sdes{ 235266077Sdes /* use arguments as temporary variables */ 236266077Sdes return sldns_wire2str_rdata_scan(&rdata, &rdata_len, &str, &str_len, 237266077Sdes rrtype, NULL, 0); 238266077Sdes} 239266077Sdes 240266077Sdesint sldns_wire2str_rr_unknown_buf(uint8_t* d, size_t dlen, char* s, size_t slen) 241266077Sdes{ 242266077Sdes /* use arguments as temporary variables */ 243266077Sdes return sldns_wire2str_rr_unknown_scan(&d, &dlen, &s, &slen, NULL, 0); 244266077Sdes} 245266077Sdes 246266077Sdesint sldns_wire2str_rr_comment_buf(uint8_t* rr, size_t rrlen, size_t dname_len, 247266077Sdes char* s, size_t slen) 248266077Sdes{ 249266077Sdes uint16_t rrtype = sldns_wirerr_get_type(rr, rrlen, dname_len); 250266077Sdes return sldns_wire2str_rr_comment_print(&s, &slen, rr, rrlen, dname_len, 251266077Sdes rrtype); 252266077Sdes} 253266077Sdes 254266077Sdesint sldns_wire2str_type_buf(uint16_t rrtype, char* s, size_t slen) 255266077Sdes{ 256266077Sdes /* use arguments as temporary variables */ 257266077Sdes return sldns_wire2str_type_print(&s, &slen, rrtype); 258266077Sdes} 259266077Sdes 260266077Sdesint sldns_wire2str_class_buf(uint16_t rrclass, char* s, size_t slen) 261266077Sdes{ 262266077Sdes /* use arguments as temporary variables */ 263266077Sdes return sldns_wire2str_class_print(&s, &slen, rrclass); 264266077Sdes} 265266077Sdes 266266077Sdesint sldns_wire2str_rcode_buf(int rcode, char* s, size_t slen) 267266077Sdes{ 268266077Sdes /* use arguments as temporary variables */ 269266077Sdes return sldns_wire2str_rcode_print(&s, &slen, rcode); 270266077Sdes} 271266077Sdes 272266077Sdesint sldns_wire2str_dname_buf(uint8_t* d, size_t dlen, char* s, size_t slen) 273266077Sdes{ 274266077Sdes /* use arguments as temporary variables */ 275266077Sdes return sldns_wire2str_dname_scan(&d, &dlen, &s, &slen, NULL, 0); 276266077Sdes} 277266077Sdes 278266077Sdesint sldns_str_vprint(char** str, size_t* slen, const char* format, va_list args) 279266077Sdes{ 280266077Sdes int w = vsnprintf(*str, *slen, format, args); 281266077Sdes if(w < 0) { 282266077Sdes /* error in printout */ 283266077Sdes return 0; 284266077Sdes } else if((size_t)w >= *slen) { 285266077Sdes *str = NULL; /* we do not want str to point outside of buffer*/ 286266077Sdes *slen = 0; 287266077Sdes } else { 288266077Sdes *str += w; 289266077Sdes *slen -= w; 290266077Sdes } 291266077Sdes return w; 292266077Sdes} 293266077Sdes 294266077Sdesint sldns_str_print(char** str, size_t* slen, const char* format, ...) 295266077Sdes{ 296266077Sdes int w; 297266077Sdes va_list args; 298266077Sdes va_start(args, format); 299266077Sdes w = sldns_str_vprint(str, slen, format, args); 300266077Sdes va_end(args); 301266077Sdes return w; 302266077Sdes} 303266077Sdes 304266077Sdes/** print hex format into text buffer for specified length */ 305266077Sdesstatic int print_hex_buf(char** s, size_t* slen, uint8_t* buf, size_t len) 306266077Sdes{ 307266077Sdes const char* hex = "0123456789ABCDEF"; 308266077Sdes size_t i; 309266077Sdes for(i=0; i<len; i++) { 310266077Sdes (void)sldns_str_print(s, slen, "%c%c", hex[(buf[i]&0xf0)>>4], 311266077Sdes hex[buf[i]&0x0f]); 312266077Sdes } 313266077Sdes return (int)len*2; 314266077Sdes} 315266077Sdes 316266077Sdes/** print remainder of buffer in hex format with prefixed text */ 317266077Sdesstatic int print_remainder_hex(const char* pref, uint8_t** d, size_t* dlen, 318266077Sdes char** s, size_t* slen) 319266077Sdes{ 320266077Sdes int w = 0; 321266077Sdes w += sldns_str_print(s, slen, "%s", pref); 322266077Sdes w += print_hex_buf(s, slen, *d, *dlen); 323266077Sdes *d += *dlen; 324266077Sdes *dlen = 0; 325266077Sdes return w; 326266077Sdes} 327266077Sdes 328266077Sdesint sldns_wire2str_pkt_scan(uint8_t** d, size_t* dlen, char** s, size_t* slen) 329266077Sdes{ 330266077Sdes int w = 0; 331266077Sdes unsigned qdcount, ancount, nscount, arcount, i; 332266077Sdes uint8_t* pkt = *d; 333266077Sdes size_t pktlen = *dlen; 334266077Sdes if(*dlen >= LDNS_HEADER_SIZE) { 335266077Sdes qdcount = (unsigned)LDNS_QDCOUNT(*d); 336266077Sdes ancount = (unsigned)LDNS_ANCOUNT(*d); 337266077Sdes nscount = (unsigned)LDNS_NSCOUNT(*d); 338266077Sdes arcount = (unsigned)LDNS_ARCOUNT(*d); 339266077Sdes } else { 340266077Sdes qdcount = ancount = nscount = arcount = 0; 341266077Sdes } 342266077Sdes w += sldns_wire2str_header_scan(d, dlen, s, slen); 343266077Sdes w += sldns_str_print(s, slen, "\n"); 344266077Sdes w += sldns_str_print(s, slen, ";; QUESTION SECTION:\n"); 345266077Sdes for(i=0; i<qdcount; i++) { 346266077Sdes w += sldns_wire2str_rrquestion_scan(d, dlen, s, slen, 347266077Sdes pkt, pktlen); 348266077Sdes if(!*dlen) break; 349266077Sdes } 350266077Sdes w += sldns_str_print(s, slen, "\n"); 351266077Sdes w += sldns_str_print(s, slen, ";; ANSWER SECTION:\n"); 352266077Sdes for(i=0; i<ancount; i++) { 353266077Sdes w += sldns_wire2str_rr_scan(d, dlen, s, slen, pkt, pktlen); 354266077Sdes if(!*dlen) break; 355266077Sdes } 356266077Sdes w += sldns_str_print(s, slen, "\n"); 357266077Sdes w += sldns_str_print(s, slen, ";; AUTHORITY SECTION:\n"); 358266077Sdes for(i=0; i<nscount; i++) { 359266077Sdes w += sldns_wire2str_rr_scan(d, dlen, s, slen, pkt, pktlen); 360266077Sdes if(!*dlen) break; 361266077Sdes } 362266077Sdes w += sldns_str_print(s, slen, "\n"); 363266077Sdes w += sldns_str_print(s, slen, ";; ADDITIONAL SECTION:\n"); 364266077Sdes for(i=0; i<arcount; i++) { 365266077Sdes w += sldns_wire2str_rr_scan(d, dlen, s, slen, pkt, pktlen); 366266077Sdes if(!*dlen) break; 367266077Sdes } 368266077Sdes /* other fields: WHEN(time), SERVER(IP) not available here. */ 369266077Sdes w += sldns_str_print(s, slen, ";; MSG SIZE rcvd: %d\n", (int)pktlen); 370266077Sdes if(*dlen > 0) { 371266077Sdes w += print_remainder_hex(";; trailing garbage 0x", 372266077Sdes d, dlen, s, slen); 373266077Sdes w += sldns_str_print(s, slen, "\n"); 374266077Sdes } 375266077Sdes return w; 376266077Sdes} 377266077Sdes 378266077Sdes/** scan type, class and ttl and printout, for rr */ 379266077Sdesstatic int sldns_rr_tcttl_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) 380266077Sdes{ 381266077Sdes int w = 0; 382266077Sdes uint16_t t, c; 383266077Sdes uint32_t ttl; 384266077Sdes if(*dl < 8) { 385266077Sdes if(*dl < 4) 386266077Sdes return w + print_remainder_hex("; Error malformed 0x", 387266077Sdes d, dl, s, sl); 388266077Sdes /* these print values or 0x.. if none left */ 389266077Sdes t = sldns_read_uint16(*d); 390266077Sdes c = sldns_read_uint16((*d)+2); 391266077Sdes (*d)+=4; 392266077Sdes (*dl)-=4; 393266077Sdes w += sldns_wire2str_class_print(s, sl, c); 394266077Sdes w += sldns_str_print(s, sl, "\t"); 395266077Sdes w += sldns_wire2str_type_print(s, sl, t); 396266077Sdes if(*dl == 0) 397266077Sdes return w + sldns_str_print(s, sl, "; Error no ttl"); 398266077Sdes return w + print_remainder_hex( 399266077Sdes "; Error malformed ttl 0x", d, dl, s, sl); 400266077Sdes } 401266077Sdes t = sldns_read_uint16(*d); 402266077Sdes c = sldns_read_uint16((*d)+2); 403266077Sdes ttl = sldns_read_uint32((*d)+4); 404266077Sdes (*d)+=8; 405266077Sdes (*dl)-=8; 406266077Sdes w += sldns_str_print(s, sl, "%lu\t", (unsigned long)ttl); 407266077Sdes w += sldns_wire2str_class_print(s, sl, c); 408266077Sdes w += sldns_str_print(s, sl, "\t"); 409266077Sdes w += sldns_wire2str_type_print(s, sl, t); 410266077Sdes return w; 411266077Sdes} 412266077Sdes 413266077Sdesint sldns_wire2str_rr_scan(uint8_t** d, size_t* dlen, char** s, size_t* slen, 414266077Sdes uint8_t* pkt, size_t pktlen) 415266077Sdes{ 416266077Sdes int w = 0; 417266077Sdes uint8_t* rr = *d; 418266077Sdes size_t rrlen = *dlen, dname_off, rdlen, ordlen; 419266077Sdes uint16_t rrtype = 0; 420266077Sdes 421266077Sdes if(*dlen >= 3 && (*d)[0]==0 && 422266077Sdes sldns_read_uint16((*d)+1)==LDNS_RR_TYPE_OPT) { 423266077Sdes /* perform EDNS OPT processing */ 424266077Sdes return sldns_wire2str_edns_scan(d, dlen, s, slen, pkt, pktlen); 425266077Sdes } 426266077Sdes 427266077Sdes /* try to scan the rdata with pretty-printing, but if that fails, then 428266077Sdes * scan the rdata as an unknown RR type */ 429266077Sdes w += sldns_wire2str_dname_scan(d, dlen, s, slen, pkt, pktlen); 430266077Sdes w += sldns_str_print(s, slen, "\t"); 431266077Sdes dname_off = rrlen-(*dlen); 432266077Sdes if(*dlen == 4) { 433266077Sdes /* like a question-RR */ 434266077Sdes uint16_t t = sldns_read_uint16(*d); 435266077Sdes uint16_t c = sldns_read_uint16((*d)+2); 436266077Sdes (*d)+=4; 437266077Sdes (*dlen)-=4; 438266077Sdes w += sldns_wire2str_class_print(s, slen, c); 439266077Sdes w += sldns_str_print(s, slen, "\t"); 440266077Sdes w += sldns_wire2str_type_print(s, slen, t); 441266077Sdes w += sldns_str_print(s, slen, " ; Error no ttl,rdata\n"); 442266077Sdes return w; 443266077Sdes } 444266077Sdes if(*dlen < 8) { 445266077Sdes if(*dlen == 0) 446266077Sdes return w + sldns_str_print(s, slen, ";Error missing RR\n"); 447266077Sdes w += print_remainder_hex(";Error partial RR 0x", d, dlen, s, slen); 448266077Sdes return w + sldns_str_print(s, slen, "\n"); 449266077Sdes } 450266077Sdes rrtype = sldns_read_uint16(*d); 451266077Sdes w += sldns_rr_tcttl_scan(d, dlen, s, slen); 452266077Sdes w += sldns_str_print(s, slen, "\t"); 453266077Sdes 454266077Sdes /* rdata */ 455266077Sdes if(*dlen < 2) { 456266077Sdes if(*dlen == 0) 457266077Sdes return w + sldns_str_print(s, slen, ";Error missing rdatalen\n"); 458266077Sdes w += print_remainder_hex(";Error missing rdatalen 0x", 459266077Sdes d, dlen, s, slen); 460266077Sdes return w + sldns_str_print(s, slen, "\n"); 461266077Sdes } 462266077Sdes rdlen = sldns_read_uint16(*d); 463266077Sdes ordlen = rdlen; 464266077Sdes (*d)+=2; 465266077Sdes (*dlen)-=2; 466266077Sdes if(*dlen < rdlen) { 467266077Sdes w += sldns_str_print(s, slen, "\\# %u ", (unsigned)rdlen); 468266077Sdes if(*dlen == 0) 469266077Sdes return w + sldns_str_print(s, slen, ";Error missing rdata\n"); 470266077Sdes w += print_remainder_hex(";Error partial rdata 0x", d, dlen, s, slen); 471266077Sdes return w + sldns_str_print(s, slen, "\n"); 472266077Sdes } 473266077Sdes w += sldns_wire2str_rdata_scan(d, &rdlen, s, slen, rrtype, pkt, pktlen); 474266077Sdes (*dlen) -= (ordlen-rdlen); 475266077Sdes 476266077Sdes /* default comment */ 477266077Sdes w += sldns_wire2str_rr_comment_print(s, slen, rr, rrlen, dname_off, 478266077Sdes rrtype); 479266077Sdes w += sldns_str_print(s, slen, "\n"); 480266077Sdes return w; 481266077Sdes} 482266077Sdes 483266077Sdesint sldns_wire2str_rrquestion_scan(uint8_t** d, size_t* dlen, char** s, 484266077Sdes size_t* slen, uint8_t* pkt, size_t pktlen) 485266077Sdes{ 486266077Sdes int w = 0; 487266077Sdes uint16_t t, c; 488266077Sdes w += sldns_wire2str_dname_scan(d, dlen, s, slen, pkt, pktlen); 489266077Sdes w += sldns_str_print(s, slen, "\t"); 490266077Sdes if(*dlen < 4) { 491266077Sdes if(*dlen == 0) 492266077Sdes return w + sldns_str_print(s, slen, "Error malformed\n"); 493266077Sdes w += print_remainder_hex("Error malformed 0x", d, dlen, s, slen); 494266077Sdes return w + sldns_str_print(s, slen, "\n"); 495266077Sdes } 496266077Sdes t = sldns_read_uint16(*d); 497266077Sdes c = sldns_read_uint16((*d)+2); 498266077Sdes (*d)+=4; 499266077Sdes (*dlen)-=4; 500266077Sdes w += sldns_wire2str_class_print(s, slen, c); 501266077Sdes w += sldns_str_print(s, slen, "\t"); 502266077Sdes w += sldns_wire2str_type_print(s, slen, t); 503266077Sdes w += sldns_str_print(s, slen, "\n"); 504266077Sdes return w; 505266077Sdes} 506266077Sdes 507266077Sdesint sldns_wire2str_rr_unknown_scan(uint8_t** d, size_t* dlen, char** s, 508266077Sdes size_t* slen, uint8_t* pkt, size_t pktlen) 509266077Sdes{ 510266077Sdes size_t rdlen, ordlen; 511266077Sdes int w = 0; 512266077Sdes w += sldns_wire2str_dname_scan(d, dlen, s, slen, pkt, pktlen); 513266077Sdes w += sldns_str_print(s, slen, "\t"); 514266077Sdes w += sldns_rr_tcttl_scan(d, dlen, s, slen); 515266077Sdes w += sldns_str_print(s, slen, "\t"); 516266077Sdes if(*dlen < 2) { 517266077Sdes if(*dlen == 0) 518266077Sdes return w + sldns_str_print(s, slen, ";Error missing rdatalen\n"); 519266077Sdes w += print_remainder_hex(";Error missing rdatalen 0x", 520266077Sdes d, dlen, s, slen); 521266077Sdes return w + sldns_str_print(s, slen, "\n"); 522266077Sdes } 523266077Sdes rdlen = sldns_read_uint16(*d); 524266077Sdes ordlen = rdlen; 525266077Sdes (*d) += 2; 526266077Sdes (*dlen) -= 2; 527266077Sdes if(*dlen < rdlen) { 528266077Sdes w += sldns_str_print(s, slen, "\\# %u ", (unsigned)rdlen); 529266077Sdes if(*dlen == 0) 530266077Sdes return w + sldns_str_print(s, slen, ";Error missing rdata\n"); 531266077Sdes w += print_remainder_hex(";Error partial rdata 0x", d, dlen, s, slen); 532266077Sdes return w + sldns_str_print(s, slen, "\n"); 533266077Sdes } 534266077Sdes w += sldns_wire2str_rdata_unknown_scan(d, &rdlen, s, slen); 535266077Sdes (*dlen) -= (ordlen-rdlen); 536266077Sdes w += sldns_str_print(s, slen, "\n"); 537266077Sdes return w; 538266077Sdes} 539266077Sdes 540266077Sdes/** print rr comment for type DNSKEY */ 541266077Sdesstatic int rr_comment_dnskey(char** s, size_t* slen, uint8_t* rr, 542266077Sdes size_t rrlen, size_t dname_off) 543266077Sdes{ 544266077Sdes size_t rdlen; 545266077Sdes uint8_t* rdata; 546266077Sdes int flags, w = 0; 547266077Sdes if(rrlen < dname_off + 10) return 0; 548266077Sdes rdlen = sldns_read_uint16(rr+dname_off+8); 549266077Sdes if(rrlen < dname_off + 10 + rdlen) return 0; 550266077Sdes rdata = rr + dname_off + 10; 551266077Sdes flags = (int)sldns_read_uint16(rdata); 552266077Sdes w += sldns_str_print(s, slen, " ;{"); 553266077Sdes 554266077Sdes /* id */ 555266077Sdes w += sldns_str_print(s, slen, "id = %u", 556266077Sdes sldns_calc_keytag_raw(rdata, rdlen)); 557266077Sdes 558266077Sdes /* flags */ 559266077Sdes if((flags&LDNS_KEY_ZONE_KEY)) { 560266077Sdes if((flags&LDNS_KEY_SEP_KEY)) 561266077Sdes w += sldns_str_print(s, slen, " (ksk)"); 562266077Sdes else w += sldns_str_print(s, slen, " (zsk)"); 563266077Sdes } 564266077Sdes 565266077Sdes /* keysize */ 566266077Sdes if(rdlen > 4) { 567266077Sdes w += sldns_str_print(s, slen, ", "); 568266077Sdes w += sldns_str_print(s, slen, "size = %db", 569266077Sdes (int)sldns_rr_dnskey_key_size_raw( 570266077Sdes (unsigned char*)rdata+4, rdlen-4, (int)(rdata[3]))); 571266077Sdes } 572266077Sdes 573266077Sdes w += sldns_str_print(s, slen, "}"); 574266077Sdes return w; 575266077Sdes} 576266077Sdes 577266077Sdes/** print rr comment for type RRSIG */ 578266077Sdesstatic int rr_comment_rrsig(char** s, size_t* slen, uint8_t* rr, 579266077Sdes size_t rrlen, size_t dname_off) 580266077Sdes{ 581266077Sdes size_t rdlen; 582266077Sdes uint8_t* rdata; 583266077Sdes if(rrlen < dname_off + 10) return 0; 584266077Sdes rdlen = sldns_read_uint16(rr+dname_off+8); 585266077Sdes if(rrlen < dname_off + 10 + rdlen) return 0; 586266077Sdes rdata = rr + dname_off + 10; 587266077Sdes if(rdlen < 18) return 0; 588266077Sdes return sldns_str_print(s, slen, " ;{id = %d}", 589266077Sdes (int)sldns_read_uint16(rdata+16)); 590266077Sdes} 591266077Sdes 592266077Sdes/** print rr comment for type NSEC3 */ 593266077Sdesstatic int rr_comment_nsec3(char** s, size_t* slen, uint8_t* rr, 594266077Sdes size_t rrlen, size_t dname_off) 595266077Sdes{ 596266077Sdes size_t rdlen; 597266077Sdes uint8_t* rdata; 598266077Sdes int w = 0; 599266077Sdes if(rrlen < dname_off + 10) return 0; 600266077Sdes rdlen = sldns_read_uint16(rr+dname_off+8); 601266077Sdes if(rrlen < dname_off + 10 + rdlen) return 0; 602266077Sdes rdata = rr + dname_off + 10; 603266077Sdes if(rdlen < 2) return 0; 604266077Sdes if((rdata[1] & LDNS_NSEC3_VARS_OPTOUT_MASK)) 605266077Sdes w += sldns_str_print(s, slen, " ;{flags: optout}"); 606266077Sdes return w; 607266077Sdes} 608266077Sdes 609266077Sdesint sldns_wire2str_rr_comment_print(char** s, size_t* slen, uint8_t* rr, 610266077Sdes size_t rrlen, size_t dname_off, uint16_t rrtype) 611266077Sdes{ 612266077Sdes if(rrtype == LDNS_RR_TYPE_DNSKEY) { 613266077Sdes return rr_comment_dnskey(s, slen, rr, rrlen, dname_off); 614266077Sdes } else if(rrtype == LDNS_RR_TYPE_RRSIG) { 615266077Sdes return rr_comment_rrsig(s, slen, rr, rrlen, dname_off); 616266077Sdes } else if(rrtype == LDNS_RR_TYPE_NSEC3) { 617266077Sdes return rr_comment_nsec3(s, slen, rr, rrlen, dname_off); 618266077Sdes } 619266077Sdes return 0; 620266077Sdes} 621266077Sdes 622266077Sdesint sldns_wire2str_header_scan(uint8_t** d, size_t* dlen, char** s, 623266077Sdes size_t* slen) 624266077Sdes{ 625266077Sdes int w = 0; 626266077Sdes int opcode, rcode; 627266077Sdes w += sldns_str_print(s, slen, ";; ->>HEADER<<- "); 628266077Sdes if(*dlen == 0) 629266077Sdes return w+sldns_str_print(s, slen, "Error empty packet"); 630266077Sdes if(*dlen < 4) 631266077Sdes return w+print_remainder_hex("Error header too short 0x", d, dlen, s, slen); 632266077Sdes opcode = (int)LDNS_OPCODE_WIRE(*d); 633266077Sdes rcode = (int)LDNS_RCODE_WIRE(*d); 634266077Sdes w += sldns_str_print(s, slen, "opcode: "); 635266077Sdes w += sldns_wire2str_opcode_print(s, slen, opcode); 636266077Sdes w += sldns_str_print(s, slen, ", "); 637266077Sdes w += sldns_str_print(s, slen, "rcode: "); 638266077Sdes w += sldns_wire2str_rcode_print(s, slen, rcode); 639266077Sdes w += sldns_str_print(s, slen, ", "); 640266077Sdes w += sldns_str_print(s, slen, "id: %d\n", (int)LDNS_ID_WIRE(*d)); 641266077Sdes w += sldns_str_print(s, slen, ";; flags:"); 642266077Sdes if(LDNS_QR_WIRE(*d)) w += sldns_str_print(s, slen, " qr"); 643266077Sdes if(LDNS_AA_WIRE(*d)) w += sldns_str_print(s, slen, " aa"); 644266077Sdes if(LDNS_TC_WIRE(*d)) w += sldns_str_print(s, slen, " tc"); 645266077Sdes if(LDNS_RD_WIRE(*d)) w += sldns_str_print(s, slen, " rd"); 646266077Sdes if(LDNS_CD_WIRE(*d)) w += sldns_str_print(s, slen, " cd"); 647266077Sdes if(LDNS_RA_WIRE(*d)) w += sldns_str_print(s, slen, " ra"); 648266077Sdes if(LDNS_AD_WIRE(*d)) w += sldns_str_print(s, slen, " ad"); 649266077Sdes if(LDNS_Z_WIRE(*d)) w += sldns_str_print(s, slen, " z"); 650266077Sdes w += sldns_str_print(s, slen, " ; "); 651266077Sdes if(*dlen < LDNS_HEADER_SIZE) 652266077Sdes return w+print_remainder_hex("Error header too short 0x", d, dlen, s, slen); 653266077Sdes w += sldns_str_print(s, slen, "QUERY: %d, ", (int)LDNS_QDCOUNT(*d)); 654266077Sdes w += sldns_str_print(s, slen, "ANSWER: %d, ", (int)LDNS_ANCOUNT(*d)); 655266077Sdes w += sldns_str_print(s, slen, "AUTHORITY: %d, ", (int)LDNS_NSCOUNT(*d)); 656266077Sdes w += sldns_str_print(s, slen, "ADDITIONAL: %d ", (int)LDNS_ARCOUNT(*d)); 657266077Sdes *d += LDNS_HEADER_SIZE; 658266077Sdes *dlen -= LDNS_HEADER_SIZE; 659266077Sdes return w; 660266077Sdes} 661266077Sdes 662266077Sdesint sldns_wire2str_rdata_scan(uint8_t** d, size_t* dlen, char** s, 663266077Sdes size_t* slen, uint16_t rrtype, uint8_t* pkt, size_t pktlen) 664266077Sdes{ 665266077Sdes /* try to prettyprint, but if that fails, use unknown format */ 666266077Sdes uint8_t* origd = *d; 667266077Sdes char* origs = *s; 668266077Sdes size_t origdlen = *dlen, origslen = *slen; 669266077Sdes uint16_t r_cnt, r_max; 670266077Sdes sldns_rdf_type rdftype; 671266077Sdes int w = 0, n; 672266077Sdes 673266077Sdes const sldns_rr_descriptor *desc = sldns_rr_descript(rrtype); 674266077Sdes if(!desc) /* unknown format */ 675266077Sdes return sldns_wire2str_rdata_unknown_scan(d, dlen, s, slen); 676266077Sdes /* dlen equals the rdatalen for the rdata */ 677266077Sdes 678266077Sdes r_max = sldns_rr_descriptor_maximum(desc); 679266077Sdes for(r_cnt=0; r_cnt < r_max; r_cnt++) { 680266077Sdes if(*dlen == 0) { 681266077Sdes if(r_cnt < sldns_rr_descriptor_minimum(desc)) 682266077Sdes goto failed; 683266077Sdes break; /* nothing more to print */ 684266077Sdes } 685266077Sdes rdftype = sldns_rr_descriptor_field_type(desc, r_cnt); 686266077Sdes if(r_cnt != 0) 687266077Sdes w += sldns_str_print(s, slen, " "); 688266077Sdes n = sldns_wire2str_rdf_scan(d, dlen, s, slen, rdftype, 689266077Sdes pkt, pktlen); 690266077Sdes if(n == -1) { 691266077Sdes failed: 692266077Sdes /* failed, use unknown format */ 693266077Sdes *d = origd; *s = origs; 694266077Sdes *dlen = origdlen; *slen = origslen; 695266077Sdes return sldns_wire2str_rdata_unknown_scan(d, dlen, 696266077Sdes s, slen); 697266077Sdes } 698266077Sdes w += n; 699266077Sdes } 700266077Sdes return w; 701266077Sdes} 702266077Sdes 703266077Sdesint sldns_wire2str_rdata_unknown_scan(uint8_t** d, size_t* dlen, char** s, 704266077Sdes size_t* slen) 705266077Sdes{ 706266077Sdes int w = 0; 707266077Sdes 708266077Sdes /* print length */ 709266077Sdes w += sldns_str_print(s, slen, "\\# %u", (unsigned)*dlen); 710266077Sdes 711266077Sdes /* print rdlen in hex */ 712266077Sdes if(*dlen != 0) 713266077Sdes w += sldns_str_print(s, slen, " "); 714266077Sdes w += print_hex_buf(s, slen, *d, *dlen); 715266077Sdes (*d) += *dlen; 716266077Sdes (*dlen) = 0; 717266077Sdes return w; 718266077Sdes} 719266077Sdes 720266077Sdes/** print and escape one character for a domain dname */ 721266077Sdesstatic int dname_char_print(char** s, size_t* slen, uint8_t c) 722266077Sdes{ 723266077Sdes if(c == '.' || c == ';' || c == '(' || c == ')' || c == '\\') 724266077Sdes return sldns_str_print(s, slen, "\\%c", c); 725266077Sdes else if(!(isascii((int)c) && isgraph((int)c))) 726266077Sdes return sldns_str_print(s, slen, "\\%03u", (unsigned)c); 727266077Sdes /* plain printout */ 728266077Sdes if(*slen) { 729266077Sdes **s = (char)c; 730266077Sdes (*s)++; 731266077Sdes (*slen)--; 732266077Sdes } 733266077Sdes return 1; 734266077Sdes} 735266077Sdes 736266077Sdesint sldns_wire2str_dname_scan(uint8_t** d, size_t* dlen, char** s, size_t* slen, 737266077Sdes uint8_t* pkt, size_t pktlen) 738266077Sdes{ 739266077Sdes int w = 0; 740266077Sdes /* spool labels onto the string, use compression if its there */ 741266077Sdes uint8_t* pos = *d; 742266077Sdes unsigned i, counter=0; 743266077Sdes const unsigned maxcompr = 1000; /* loop detection, max compr ptrs */ 744266077Sdes int in_buf = 1; 745266077Sdes if(*dlen == 0) return sldns_str_print(s, slen, "ErrorMissingDname"); 746266077Sdes if(*pos == 0) { 747266077Sdes (*d)++; 748266077Sdes (*dlen)--; 749266077Sdes return sldns_str_print(s, slen, "."); 750266077Sdes } 751266077Sdes while(*pos) { 752266077Sdes /* read label length */ 753266077Sdes uint8_t labellen = *pos++; 754266077Sdes if(in_buf) { (*d)++; (*dlen)--; } 755266077Sdes 756266077Sdes /* find out what sort of label we have */ 757266077Sdes if((labellen&0xc0) == 0xc0) { 758266077Sdes /* compressed */ 759266077Sdes uint16_t target = 0; 760266077Sdes if(in_buf && *dlen == 0) 761266077Sdes return w + sldns_str_print(s, slen, 762266077Sdes "ErrorPartialDname"); 763266077Sdes else if(!in_buf && pos+1 > pkt+pktlen) 764266077Sdes return w + sldns_str_print(s, slen, 765266077Sdes "ErrorPartialDname"); 766266077Sdes target = ((labellen&0x3f)<<8) | *pos; 767266077Sdes if(in_buf) { (*d)++; (*dlen)--; } 768266077Sdes /* move to target, if possible */ 769266077Sdes if(!pkt || target >= pktlen) 770266077Sdes return w + sldns_str_print(s, slen, 771266077Sdes "ErrorComprPtrOutOfBounds"); 772266077Sdes if(counter++ > maxcompr) 773266077Sdes return w + sldns_str_print(s, slen, 774266077Sdes "ErrorComprPtrLooped"); 775266077Sdes in_buf = 0; 776266077Sdes pos = pkt+target; 777266077Sdes continue; 778266077Sdes } else if((labellen&0xc0)) { 779266077Sdes /* notimpl label type */ 780266077Sdes w += sldns_str_print(s, slen, 781266077Sdes "ErrorLABELTYPE%xIsUnknown", 782266077Sdes (int)(labellen&0xc0)); 783266077Sdes return w; 784266077Sdes } 785266077Sdes 786266077Sdes /* spool label characters, end with '.' */ 787266077Sdes if(in_buf && *dlen < labellen) labellen = *dlen; 788266077Sdes else if(!in_buf && pos+labellen > pkt+pktlen) 789266077Sdes labellen = (uint8_t)(pkt + pktlen - pos); 790266077Sdes for(i=0; i<(unsigned)labellen; i++) { 791266077Sdes w += dname_char_print(s, slen, *pos++); 792266077Sdes } 793266077Sdes if(in_buf) { 794266077Sdes (*d) += labellen; 795266077Sdes (*dlen) -= labellen; 796266077Sdes if(*dlen == 0) break; 797266077Sdes } 798266077Sdes w += sldns_str_print(s, slen, "."); 799266077Sdes } 800266077Sdes /* skip over final root label */ 801266077Sdes if(in_buf && *dlen > 0) { (*d)++; (*dlen)--; } 802266077Sdes /* in case we printed no labels, terminate dname */ 803266077Sdes if(w == 0) w += sldns_str_print(s, slen, "."); 804266077Sdes return w; 805266077Sdes} 806266077Sdes 807266077Sdesint sldns_wire2str_opcode_print(char** s, size_t* slen, int opcode) 808266077Sdes{ 809266077Sdes sldns_lookup_table *lt = sldns_lookup_by_id(sldns_opcodes, opcode); 810266077Sdes if (lt && lt->name) { 811266077Sdes return sldns_str_print(s, slen, "%s", lt->name); 812266077Sdes } 813266077Sdes return sldns_str_print(s, slen, "OPCODE%u", (unsigned)opcode); 814266077Sdes} 815266077Sdes 816266077Sdesint sldns_wire2str_rcode_print(char** s, size_t* slen, int rcode) 817266077Sdes{ 818266077Sdes sldns_lookup_table *lt = sldns_lookup_by_id(sldns_rcodes, rcode); 819266077Sdes if (lt && lt->name) { 820266077Sdes return sldns_str_print(s, slen, "%s", lt->name); 821266077Sdes } 822266077Sdes return sldns_str_print(s, slen, "RCODE%u", (unsigned)rcode); 823266077Sdes} 824266077Sdes 825266077Sdesint sldns_wire2str_class_print(char** s, size_t* slen, uint16_t rrclass) 826266077Sdes{ 827266077Sdes sldns_lookup_table *lt = sldns_lookup_by_id(sldns_rr_classes, 828266077Sdes (int)rrclass); 829266077Sdes if (lt && lt->name) { 830266077Sdes return sldns_str_print(s, slen, "%s", lt->name); 831266077Sdes } 832266077Sdes return sldns_str_print(s, slen, "CLASS%u", (unsigned)rrclass); 833266077Sdes} 834266077Sdes 835266077Sdesint sldns_wire2str_type_print(char** s, size_t* slen, uint16_t rrtype) 836266077Sdes{ 837266077Sdes const sldns_rr_descriptor *descriptor = sldns_rr_descript(rrtype); 838266077Sdes if (descriptor && descriptor->_name) { 839266077Sdes return sldns_str_print(s, slen, "%s", descriptor->_name); 840266077Sdes } 841266077Sdes return sldns_str_print(s, slen, "TYPE%u", (unsigned)rrtype); 842266077Sdes} 843266077Sdes 844266077Sdesint sldns_wire2str_edns_option_code_print(char** s, size_t* slen, 845266077Sdes uint16_t opcode) 846266077Sdes{ 847266077Sdes sldns_lookup_table *lt = sldns_lookup_by_id(sldns_edns_options, 848266077Sdes (int)opcode); 849266077Sdes if (lt && lt->name) { 850266077Sdes return sldns_str_print(s, slen, "%s", lt->name); 851266077Sdes } 852266077Sdes return sldns_str_print(s, slen, "OPT%u", (unsigned)opcode); 853266077Sdes} 854266077Sdes 855266077Sdesint sldns_wire2str_class_scan(uint8_t** d, size_t* dlen, char** s, size_t* slen) 856266077Sdes{ 857266077Sdes uint16_t c; 858266077Sdes if(*dlen == 0) return 0; 859266077Sdes if(*dlen < 2) return print_remainder_hex("Error malformed 0x", d, dlen, s, slen); 860266077Sdes c = sldns_read_uint16(*d); 861266077Sdes (*d)+=2; 862266077Sdes (*dlen)-=2; 863266077Sdes return sldns_wire2str_class_print(s, slen, c); 864266077Sdes} 865266077Sdes 866266077Sdesint sldns_wire2str_type_scan(uint8_t** d, size_t* dlen, char** s, size_t* slen) 867266077Sdes{ 868266077Sdes uint16_t t; 869266077Sdes if(*dlen == 0) return 0; 870266077Sdes if(*dlen < 2) return print_remainder_hex("Error malformed 0x", d, dlen, s, slen); 871266077Sdes t = sldns_read_uint16(*d); 872266077Sdes (*d)+=2; 873266077Sdes (*dlen)-=2; 874266077Sdes return sldns_wire2str_type_print(s, slen, t); 875266077Sdes} 876266077Sdes 877266077Sdesint sldns_wire2str_ttl_scan(uint8_t** d, size_t* dlen, char** s, size_t* slen) 878266077Sdes{ 879266077Sdes uint32_t ttl; 880266077Sdes if(*dlen == 0) return 0; 881266077Sdes if(*dlen < 4) return print_remainder_hex("Error malformed 0x", d, dlen, s, slen); 882266077Sdes ttl = sldns_read_uint32(*d); 883266077Sdes (*d)+=4; 884266077Sdes (*dlen)-=4; 885266077Sdes return sldns_str_print(s, slen, "%u", (unsigned)ttl); 886266077Sdes} 887266077Sdes 888266077Sdesint sldns_wire2str_rdf_scan(uint8_t** d, size_t* dlen, char** s, size_t* slen, 889266077Sdes int rdftype, uint8_t* pkt, size_t pktlen) 890266077Sdes{ 891266077Sdes if(*dlen == 0) return 0; 892266077Sdes switch(rdftype) { 893266077Sdes case LDNS_RDF_TYPE_NONE: 894266077Sdes return 0; 895266077Sdes case LDNS_RDF_TYPE_DNAME: 896266077Sdes return sldns_wire2str_dname_scan(d, dlen, s, slen, pkt, pktlen); 897266077Sdes case LDNS_RDF_TYPE_INT8: 898266077Sdes return sldns_wire2str_int8_scan(d, dlen, s, slen); 899266077Sdes case LDNS_RDF_TYPE_INT16: 900266077Sdes return sldns_wire2str_int16_scan(d, dlen, s, slen); 901266077Sdes case LDNS_RDF_TYPE_INT32: 902266077Sdes return sldns_wire2str_int32_scan(d, dlen, s, slen); 903266077Sdes case LDNS_RDF_TYPE_PERIOD: 904266077Sdes return sldns_wire2str_period_scan(d, dlen, s, slen); 905266077Sdes case LDNS_RDF_TYPE_TSIGTIME: 906266077Sdes return sldns_wire2str_tsigtime_scan(d, dlen, s, slen); 907266077Sdes case LDNS_RDF_TYPE_A: 908266077Sdes return sldns_wire2str_a_scan(d, dlen, s, slen); 909266077Sdes case LDNS_RDF_TYPE_AAAA: 910266077Sdes return sldns_wire2str_aaaa_scan(d, dlen, s, slen); 911266077Sdes case LDNS_RDF_TYPE_STR: 912266077Sdes return sldns_wire2str_str_scan(d, dlen, s, slen); 913266077Sdes case LDNS_RDF_TYPE_APL: 914266077Sdes return sldns_wire2str_apl_scan(d, dlen, s, slen); 915266077Sdes case LDNS_RDF_TYPE_B32_EXT: 916266077Sdes return sldns_wire2str_b32_ext_scan(d, dlen, s, slen); 917266077Sdes case LDNS_RDF_TYPE_B64: 918266077Sdes return sldns_wire2str_b64_scan(d, dlen, s, slen); 919266077Sdes case LDNS_RDF_TYPE_HEX: 920266077Sdes return sldns_wire2str_hex_scan(d, dlen, s, slen); 921266077Sdes case LDNS_RDF_TYPE_NSEC: 922266077Sdes return sldns_wire2str_nsec_scan(d, dlen, s, slen); 923266077Sdes case LDNS_RDF_TYPE_NSEC3_SALT: 924266077Sdes return sldns_wire2str_nsec3_salt_scan(d, dlen, s, slen); 925266077Sdes case LDNS_RDF_TYPE_TYPE: 926266077Sdes return sldns_wire2str_type_scan(d, dlen, s, slen); 927266077Sdes case LDNS_RDF_TYPE_CLASS: 928266077Sdes return sldns_wire2str_class_scan(d, dlen, s, slen); 929266077Sdes case LDNS_RDF_TYPE_CERT_ALG: 930266077Sdes return sldns_wire2str_cert_alg_scan(d, dlen, s, slen); 931266077Sdes case LDNS_RDF_TYPE_ALG: 932266077Sdes return sldns_wire2str_alg_scan(d, dlen, s, slen); 933266077Sdes case LDNS_RDF_TYPE_UNKNOWN: 934266077Sdes return sldns_wire2str_unknown_scan(d, dlen, s, slen); 935266077Sdes case LDNS_RDF_TYPE_TIME: 936266077Sdes return sldns_wire2str_time_scan(d, dlen, s, slen); 937266077Sdes case LDNS_RDF_TYPE_LOC: 938266077Sdes return sldns_wire2str_loc_scan(d, dlen, s, slen); 939266077Sdes case LDNS_RDF_TYPE_WKS: 940266077Sdes case LDNS_RDF_TYPE_SERVICE: 941266077Sdes return sldns_wire2str_wks_scan(d, dlen, s, slen); 942266077Sdes case LDNS_RDF_TYPE_NSAP: 943266077Sdes return sldns_wire2str_nsap_scan(d, dlen, s, slen); 944266077Sdes case LDNS_RDF_TYPE_ATMA: 945266077Sdes return sldns_wire2str_atma_scan(d, dlen, s, slen); 946266077Sdes case LDNS_RDF_TYPE_IPSECKEY: 947266077Sdes return sldns_wire2str_ipseckey_scan(d, dlen, s, slen, pkt, 948266077Sdes pktlen); 949266077Sdes case LDNS_RDF_TYPE_HIP: 950266077Sdes return sldns_wire2str_hip_scan(d, dlen, s, slen); 951266077Sdes case LDNS_RDF_TYPE_INT16_DATA: 952266077Sdes return sldns_wire2str_int16_data_scan(d, dlen, s, slen); 953266077Sdes case LDNS_RDF_TYPE_NSEC3_NEXT_OWNER: 954266077Sdes return sldns_wire2str_b32_ext_scan(d, dlen, s, slen); 955266077Sdes case LDNS_RDF_TYPE_ILNP64: 956266077Sdes return sldns_wire2str_ilnp64_scan(d, dlen, s, slen); 957266077Sdes case LDNS_RDF_TYPE_EUI48: 958266077Sdes return sldns_wire2str_eui48_scan(d, dlen, s, slen); 959266077Sdes case LDNS_RDF_TYPE_EUI64: 960266077Sdes return sldns_wire2str_eui64_scan(d, dlen, s, slen); 961266077Sdes case LDNS_RDF_TYPE_TAG: 962266077Sdes return sldns_wire2str_tag_scan(d, dlen, s, slen); 963266077Sdes case LDNS_RDF_TYPE_LONG_STR: 964266077Sdes return sldns_wire2str_long_str_scan(d, dlen, s, slen); 965266077Sdes } 966266077Sdes /* unknown rdf type */ 967266077Sdes return -1; 968266077Sdes} 969266077Sdes 970266077Sdesint sldns_wire2str_int8_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) 971266077Sdes{ 972266077Sdes int w; 973266077Sdes if(*dl < 1) return -1; 974266077Sdes w = sldns_str_print(s, sl, "%u", (unsigned)**d); 975266077Sdes (*d)++; 976266077Sdes (*dl)--; 977266077Sdes return w; 978266077Sdes} 979266077Sdes 980266077Sdesint sldns_wire2str_int16_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) 981266077Sdes{ 982266077Sdes int w; 983266077Sdes if(*dl < 2) return -1; 984266077Sdes w = sldns_str_print(s, sl, "%lu", (unsigned long)sldns_read_uint16(*d)); 985266077Sdes (*d)+=2; 986266077Sdes (*dl)-=2; 987266077Sdes return w; 988266077Sdes} 989266077Sdes 990266077Sdesint sldns_wire2str_int32_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) 991266077Sdes{ 992266077Sdes int w; 993266077Sdes if(*dl < 4) return -1; 994266077Sdes w = sldns_str_print(s, sl, "%lu", (unsigned long)sldns_read_uint32(*d)); 995266077Sdes (*d)+=4; 996266077Sdes (*dl)-=4; 997266077Sdes return w; 998266077Sdes} 999266077Sdes 1000266077Sdesint sldns_wire2str_period_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) 1001266077Sdes{ 1002266077Sdes int w; 1003266077Sdes if(*dl < 4) return -1; 1004266077Sdes w = sldns_str_print(s, sl, "%u", (unsigned)sldns_read_uint32(*d)); 1005266077Sdes (*d)+=4; 1006266077Sdes (*dl)-=4; 1007266077Sdes return w; 1008266077Sdes} 1009266077Sdes 1010266077Sdesint sldns_wire2str_tsigtime_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) 1011266077Sdes{ 1012266077Sdes /* tsigtime is 48 bits network order unsigned integer */ 1013266077Sdes int w; 1014266077Sdes uint64_t tsigtime = 0; 1015266077Sdes uint64_t d0, d1, d2, d3, d4, d5; 1016266077Sdes if(*dl < 6) return -1; 1017266077Sdes d0 = (*d)[0]; /* cast to uint64 for shift operations */ 1018266077Sdes d1 = (*d)[1]; 1019266077Sdes d2 = (*d)[2]; 1020266077Sdes d3 = (*d)[3]; 1021266077Sdes d4 = (*d)[4]; 1022266077Sdes d5 = (*d)[5]; 1023266077Sdes tsigtime = (d0<<40) | (d1<<32) | (d2<<24) | (d3<<16) | (d4<<8) | d5; 1024266077Sdes#ifndef USE_WINSOCK 1025266077Sdes w = sldns_str_print(s, sl, "%llu", (long long)tsigtime); 1026266077Sdes#else 1027266077Sdes w = sldns_str_print(s, sl, "%I64u", (long long)tsigtime); 1028266077Sdes#endif 1029266077Sdes (*d)+=6; 1030266077Sdes (*dl)-=6; 1031266077Sdes return w; 1032266077Sdes} 1033266077Sdes 1034266077Sdesint sldns_wire2str_a_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) 1035266077Sdes{ 1036266077Sdes char buf[32]; 1037266077Sdes int w; 1038266077Sdes if(*dl < 4) return -1; 1039266077Sdes if(!inet_ntop(AF_INET, *d, buf, (socklen_t)sizeof(buf))) 1040266077Sdes return -1; 1041266077Sdes w = sldns_str_print(s, sl, "%s", buf); 1042266077Sdes (*d)+=4; 1043266077Sdes (*dl)-=4; 1044266077Sdes return w; 1045266077Sdes} 1046266077Sdes 1047266077Sdesint sldns_wire2str_aaaa_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) 1048266077Sdes{ 1049266077Sdes#ifdef AF_INET6 1050266077Sdes char buf[64]; 1051266077Sdes int w; 1052266077Sdes if(*dl < 16) return -1; 1053266077Sdes if(!inet_ntop(AF_INET6, *d, buf, (socklen_t)sizeof(buf))) 1054266077Sdes return -1; 1055266077Sdes w = sldns_str_print(s, sl, "%s", buf); 1056266077Sdes (*d)+=16; 1057266077Sdes (*dl)-=16; 1058266077Sdes return w; 1059266077Sdes#else 1060266077Sdes return -1; 1061266077Sdes#endif 1062266077Sdes} 1063266077Sdes 1064266077Sdes/** printout escaped TYPE_STR character */ 1065266077Sdesstatic int str_char_print(char** s, size_t* sl, uint8_t c) 1066266077Sdes{ 1067266077Sdes if(isprint((int)c) || c == '\t') { 1068266077Sdes if(c == '\"' || c == '\\') 1069266077Sdes return sldns_str_print(s, sl, "\\%c", c); 1070266077Sdes if(*sl) { 1071266077Sdes **s = (char)c; 1072266077Sdes (*s)++; 1073266077Sdes (*sl)--; 1074266077Sdes } 1075266077Sdes return 1; 1076266077Sdes } 1077266077Sdes return sldns_str_print(s, sl, "\\%03u", (unsigned)c); 1078266077Sdes} 1079266077Sdes 1080266077Sdesint sldns_wire2str_str_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) 1081266077Sdes{ 1082266077Sdes int w = 0; 1083266077Sdes size_t i, len; 1084266077Sdes if(*dl < 1) return -1; 1085266077Sdes len = **d; 1086266077Sdes if(*dl < 1+len) return -1; 1087266077Sdes (*d)++; 1088266077Sdes (*dl)--; 1089266077Sdes w += sldns_str_print(s, sl, "\""); 1090266077Sdes for(i=0; i<len; i++) 1091266077Sdes w += str_char_print(s, sl, (*d)[i]); 1092266077Sdes w += sldns_str_print(s, sl, "\""); 1093266077Sdes (*d)+=len; 1094266077Sdes (*dl)-=len; 1095266077Sdes return w; 1096266077Sdes} 1097266077Sdes 1098266077Sdesint sldns_wire2str_apl_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) 1099266077Sdes{ 1100266077Sdes int i, w = 0; 1101266077Sdes uint16_t family; 1102266077Sdes uint8_t negation, prefix, adflength; 1103266077Sdes if(*dl < 4) return -1; 1104266077Sdes family = sldns_read_uint16(*d); 1105266077Sdes prefix = (*d)[2]; 1106266077Sdes negation = ((*d)[3] & LDNS_APL_NEGATION); 1107266077Sdes adflength = ((*d)[3] & LDNS_APL_MASK); 1108266077Sdes if(*dl < 4+(size_t)adflength) return -1; 1109266077Sdes if(family != LDNS_APL_IP4 && family != LDNS_APL_IP6) 1110266077Sdes return -1; /* unknown address family */ 1111266077Sdes if(negation) 1112266077Sdes w += sldns_str_print(s, sl, "!"); 1113266077Sdes w += sldns_str_print(s, sl, "%u:", (unsigned)family); 1114266077Sdes if(family == LDNS_APL_IP4) { 1115266077Sdes /* check if prefix <32 ? */ 1116266077Sdes /* address is variable length 0 - 4 */ 1117266077Sdes for(i=0; i<4; i++) { 1118266077Sdes if(i > 0) 1119266077Sdes w += sldns_str_print(s, sl, "."); 1120266077Sdes if(i < (int)adflength) 1121266077Sdes w += sldns_str_print(s, sl, "%d", (*d)[4+i]); 1122266077Sdes else w += sldns_str_print(s, sl, "0"); 1123266077Sdes } 1124266077Sdes } else if(family == LDNS_APL_IP6) { 1125266077Sdes /* check if prefix <128 ? */ 1126266077Sdes /* address is variable length 0 - 16 */ 1127266077Sdes for(i=0; i<16; i++) { 1128266077Sdes if(i%2 == 0 && i>0) 1129266077Sdes w += sldns_str_print(s, sl, ":"); 1130266077Sdes if(i < (int)adflength) 1131266077Sdes w += sldns_str_print(s, sl, "%02x", (*d)[4+i]); 1132266077Sdes else w += sldns_str_print(s, sl, "00"); 1133266077Sdes } 1134266077Sdes } 1135266077Sdes w += sldns_str_print(s, sl, "/%u", (unsigned)prefix); 1136266077Sdes (*d) += 4+adflength; 1137266077Sdes (*dl) -= 4+adflength; 1138266077Sdes return w; 1139266077Sdes} 1140266077Sdes 1141266077Sdesint sldns_wire2str_b32_ext_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) 1142266077Sdes{ 1143266077Sdes size_t datalen; 1144266077Sdes size_t sz; 1145266077Sdes if(*dl < 1) return -1; 1146266077Sdes datalen = (*d)[0]; 1147266077Sdes if(*dl < 1+datalen) return -1; 1148266077Sdes sz = sldns_b32_ntop_calculate_size(datalen); 1149266077Sdes if(*sl < sz+1) { 1150266077Sdes (*d) += datalen+1; 1151266077Sdes (*dl) -= (datalen+1); 1152266077Sdes return (int)sz; /* out of space really, but would need buffer 1153266077Sdes in order to truncate the output */ 1154266077Sdes } 1155266077Sdes sldns_b32_ntop_extended_hex((*d)+1, datalen, *s, *sl); 1156266077Sdes (*d) += datalen+1; 1157266077Sdes (*dl) -= (datalen+1); 1158266077Sdes (*s) += sz; 1159266077Sdes (*sl) -= sz; 1160266077Sdes return (int)sz; 1161266077Sdes} 1162266077Sdes 1163266077Sdes/** scan number of bytes from wire into b64 presentation format */ 1164266077Sdesstatic int sldns_wire2str_b64_scan_num(uint8_t** d, size_t* dl, char** s, 1165266077Sdes size_t* sl, size_t num) 1166266077Sdes{ 1167266077Sdes /* b64_ntop_calculate size includes null at the end */ 1168266077Sdes size_t sz = sldns_b64_ntop_calculate_size(num)-1; 1169266077Sdes if(*sl < sz+1) { 1170266077Sdes (*d) += num; 1171266077Sdes (*dl) -= num; 1172266077Sdes return (int)sz; /* out of space really, but would need buffer 1173266077Sdes in order to truncate the output */ 1174266077Sdes } 1175266077Sdes sldns_b64_ntop(*d, num, *s, *sl); 1176266077Sdes (*d) += num; 1177266077Sdes (*dl) -= num; 1178266077Sdes (*s) += sz; 1179266077Sdes (*sl) -= sz; 1180266077Sdes return (int)sz; 1181266077Sdes} 1182266077Sdes 1183266077Sdesint sldns_wire2str_b64_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) 1184266077Sdes{ 1185266077Sdes return sldns_wire2str_b64_scan_num(d, dl, s, sl, *dl); 1186266077Sdes} 1187266077Sdes 1188266077Sdesint sldns_wire2str_hex_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) 1189266077Sdes{ 1190266077Sdes return print_remainder_hex("", d, dl, s, sl); 1191266077Sdes} 1192266077Sdes 1193266077Sdesint sldns_wire2str_nsec_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) 1194266077Sdes{ 1195266077Sdes uint8_t* p = *d; 1196266077Sdes size_t pl = *dl; 1197266077Sdes unsigned i, bit, window, block_len; 1198266077Sdes uint16_t t; 1199266077Sdes int w = 0; 1200266077Sdes 1201266077Sdes /* check for errors */ 1202266077Sdes while(pl) { 1203266077Sdes if(pl < 2) return -1; 1204266077Sdes block_len = (unsigned)p[1]; 1205266077Sdes if(pl < 2+block_len) return -1; 1206266077Sdes p += block_len+2; 1207266077Sdes pl -= block_len+2; 1208266077Sdes } 1209266077Sdes 1210266077Sdes /* do it */ 1211266077Sdes p = *d; 1212266077Sdes pl = *dl; 1213266077Sdes while(pl) { 1214266077Sdes if(pl < 2) return -1; /* cannot happen */ 1215266077Sdes window = (unsigned)p[0]; 1216266077Sdes block_len = (unsigned)p[1]; 1217266077Sdes if(pl < 2+block_len) return -1; /* cannot happen */ 1218266077Sdes p += 2; 1219266077Sdes for(i=0; i<block_len; i++) { 1220266077Sdes if(p[i] == 0) continue; 1221266077Sdes /* base type number for this octet */ 1222266077Sdes t = ((window)<<8) | (i << 3); 1223266077Sdes for(bit=0; bit<8; bit++) { 1224266077Sdes if((p[i]&(0x80>>bit))) { 1225266077Sdes if(w) w += sldns_str_print(s, sl, " "); 1226266077Sdes w += sldns_wire2str_type_print(s, sl, 1227266077Sdes t+bit); 1228266077Sdes } 1229266077Sdes } 1230266077Sdes } 1231266077Sdes p += block_len; 1232266077Sdes pl -= block_len+2; 1233266077Sdes } 1234266077Sdes (*d) += *dl; 1235266077Sdes (*dl) = 0; 1236266077Sdes return w; 1237266077Sdes} 1238266077Sdes 1239266077Sdesint sldns_wire2str_nsec3_salt_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) 1240266077Sdes{ 1241266077Sdes size_t salt_len; 1242266077Sdes int w; 1243266077Sdes if(*dl < 1) return -1; 1244266077Sdes salt_len = (size_t)(*d)[0]; 1245266077Sdes if(*dl < 1+salt_len) return -1; 1246266077Sdes (*d)++; 1247266077Sdes (*dl)--; 1248266077Sdes if(salt_len == 0) { 1249266077Sdes return sldns_str_print(s, sl, "-"); 1250266077Sdes } 1251266077Sdes w = print_hex_buf(s, sl, *d, salt_len); 1252266077Sdes (*dl)-=salt_len; 1253266077Sdes (*d)+=salt_len; 1254266077Sdes return w; 1255266077Sdes} 1256266077Sdes 1257266077Sdesint sldns_wire2str_cert_alg_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) 1258266077Sdes{ 1259266077Sdes sldns_lookup_table *lt; 1260266077Sdes int data, w; 1261266077Sdes if(*dl < 2) return -1; 1262266077Sdes data = (int)sldns_read_uint16(*d); 1263266077Sdes lt = sldns_lookup_by_id(sldns_cert_algorithms, data); 1264266077Sdes if(lt && lt->name) 1265266077Sdes w = sldns_str_print(s, sl, "%s", lt->name); 1266266077Sdes else w = sldns_str_print(s, sl, "%d", data); 1267266077Sdes (*dl)-=2; 1268266077Sdes (*d)+=2; 1269266077Sdes return w; 1270266077Sdes} 1271266077Sdes 1272266077Sdesint sldns_wire2str_alg_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) 1273266077Sdes{ 1274266077Sdes /* don't use algorithm mnemonics in the presentation format 1275266077Sdes * this kind of got sneaked into the rfc's */ 1276266077Sdes return sldns_wire2str_int8_scan(d, dl, s, sl); 1277266077Sdes} 1278266077Sdes 1279266077Sdesint sldns_wire2str_unknown_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) 1280266077Sdes{ 1281266077Sdes return sldns_wire2str_rdata_unknown_scan(d, dl, s, sl); 1282266077Sdes} 1283266077Sdes 1284266077Sdesint sldns_wire2str_time_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) 1285266077Sdes{ 1286266077Sdes /* create a YYYYMMDDHHMMSS string if possible */ 1287266077Sdes struct tm tm; 1288266077Sdes char date_buf[16]; 1289266077Sdes uint32_t t; 1290266077Sdes memset(&tm, 0, sizeof(tm)); 1291266077Sdes if(*dl < 4) return -1; 1292266077Sdes t = sldns_read_uint32(*d); 1293266077Sdes date_buf[15]=0; 1294266077Sdes if(sldns_serial_arithmitics_gmtime_r(t, time(NULL), &tm) && 1295266077Sdes strftime(date_buf, 15, "%Y%m%d%H%M%S", &tm)) { 1296266077Sdes (*d) += 4; 1297266077Sdes (*dl) -= 4; 1298266077Sdes return sldns_str_print(s, sl, "%s", date_buf); 1299266077Sdes } 1300266077Sdes return -1; 1301266077Sdes} 1302266077Sdes 1303266077Sdesstatic int 1304266077Sdesloc_cm_print(char** str, size_t* sl, uint8_t mantissa, uint8_t exponent) 1305266077Sdes{ 1306266077Sdes int w = 0; 1307266077Sdes uint8_t i; 1308266077Sdes /* is it 0.<two digits> ? */ 1309266077Sdes if(exponent < 2) { 1310266077Sdes if(exponent == 1) 1311266077Sdes mantissa *= 10; 1312266077Sdes return sldns_str_print(str, sl, "0.%02ld", (long)mantissa); 1313266077Sdes } 1314266077Sdes /* always <digit><string of zeros> */ 1315266077Sdes w += sldns_str_print(str, sl, "%d", (int)mantissa); 1316266077Sdes for(i=0; i<exponent-2; i++) 1317266077Sdes w += sldns_str_print(str, sl, "0"); 1318266077Sdes return w; 1319266077Sdes} 1320266077Sdes 1321266077Sdesint sldns_wire2str_loc_scan(uint8_t** d, size_t* dl, char** str, size_t* sl) 1322266077Sdes{ 1323266077Sdes /* we could do checking (ie degrees < 90 etc)? */ 1324266077Sdes uint8_t version; 1325266077Sdes uint8_t size; 1326266077Sdes uint8_t horizontal_precision; 1327266077Sdes uint8_t vertical_precision; 1328266077Sdes uint32_t longitude; 1329266077Sdes uint32_t latitude; 1330266077Sdes uint32_t altitude; 1331266077Sdes char northerness; 1332266077Sdes char easterness; 1333266077Sdes uint32_t h; 1334266077Sdes uint32_t m; 1335266077Sdes double s; 1336266077Sdes uint32_t equator = (uint32_t)1 << 31; /* 2**31 */ 1337266077Sdes int w = 0; 1338266077Sdes 1339266077Sdes if(*dl < 16) return -1; 1340266077Sdes version = (*d)[0]; 1341266077Sdes if(version != 0) 1342266077Sdes return sldns_wire2str_hex_scan(d, dl, str, sl); 1343266077Sdes size = (*d)[1]; 1344266077Sdes horizontal_precision = (*d)[2]; 1345266077Sdes vertical_precision = (*d)[3]; 1346266077Sdes 1347266077Sdes latitude = sldns_read_uint32((*d)+4); 1348266077Sdes longitude = sldns_read_uint32((*d)+8); 1349266077Sdes altitude = sldns_read_uint32((*d)+12); 1350266077Sdes 1351266077Sdes if (latitude > equator) { 1352266077Sdes northerness = 'N'; 1353266077Sdes latitude = latitude - equator; 1354266077Sdes } else { 1355266077Sdes northerness = 'S'; 1356266077Sdes latitude = equator - latitude; 1357266077Sdes } 1358266077Sdes h = latitude / (1000 * 60 * 60); 1359266077Sdes latitude = latitude % (1000 * 60 * 60); 1360266077Sdes m = latitude / (1000 * 60); 1361266077Sdes latitude = latitude % (1000 * 60); 1362266077Sdes s = (double) latitude / 1000.0; 1363266077Sdes w += sldns_str_print(str, sl, "%02u %02u %06.3f %c ", 1364266077Sdes h, m, s, northerness); 1365266077Sdes 1366266077Sdes if (longitude > equator) { 1367266077Sdes easterness = 'E'; 1368266077Sdes longitude = longitude - equator; 1369266077Sdes } else { 1370266077Sdes easterness = 'W'; 1371266077Sdes longitude = equator - longitude; 1372266077Sdes } 1373266077Sdes h = longitude / (1000 * 60 * 60); 1374266077Sdes longitude = longitude % (1000 * 60 * 60); 1375266077Sdes m = longitude / (1000 * 60); 1376266077Sdes longitude = longitude % (1000 * 60); 1377266077Sdes s = (double) longitude / (1000.0); 1378266077Sdes w += sldns_str_print(str, sl, "%02u %02u %06.3f %c ", 1379266077Sdes h, m, s, easterness); 1380266077Sdes 1381266077Sdes s = ((double) altitude) / 100; 1382266077Sdes s -= 100000; 1383266077Sdes 1384266077Sdes if(altitude%100 != 0) 1385266077Sdes w += sldns_str_print(str, sl, "%.2f", s); 1386266077Sdes else 1387266077Sdes w += sldns_str_print(str, sl, "%.0f", s); 1388266077Sdes 1389266077Sdes w += sldns_str_print(str, sl, "m "); 1390266077Sdes 1391266077Sdes w += loc_cm_print(str, sl, (size & 0xf0) >> 4, size & 0x0f); 1392266077Sdes w += sldns_str_print(str, sl, "m "); 1393266077Sdes 1394266077Sdes w += loc_cm_print(str, sl, (horizontal_precision & 0xf0) >> 4, 1395266077Sdes horizontal_precision & 0x0f); 1396266077Sdes w += sldns_str_print(str, sl, "m "); 1397266077Sdes 1398266077Sdes w += loc_cm_print(str, sl, (vertical_precision & 0xf0) >> 4, 1399266077Sdes vertical_precision & 0x0f); 1400266077Sdes w += sldns_str_print(str, sl, "m"); 1401266077Sdes 1402266077Sdes (*d)+=16; 1403266077Sdes (*dl)-=16; 1404266077Sdes return w; 1405266077Sdes} 1406266077Sdes 1407266077Sdesint sldns_wire2str_wks_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) 1408266077Sdes{ 1409266077Sdes /* protocol, followed by bitmap of services */ 1410266077Sdes const char* proto_name = NULL; 1411266077Sdes struct protoent *protocol; 1412266077Sdes struct servent *service; 1413266077Sdes uint8_t protocol_nr; 1414266077Sdes int bit, port, w = 0; 1415266077Sdes size_t i; 1416266077Sdes /* we cannot print with strings because they 1417266077Sdes * are not portable, the presentation format may 1418266077Sdes * not be able to be read in on another computer. */ 1419266077Sdes int print_symbols = 0; 1420266077Sdes 1421266077Sdes /* protocol */ 1422266077Sdes if(*dl < 1) return -1; 1423266077Sdes protocol_nr = (*d)[0]; 1424266077Sdes (*d)++; 1425266077Sdes (*dl)--; 1426266077Sdes protocol = getprotobynumber((int)protocol_nr); 1427266077Sdes if(protocol && (protocol->p_name != NULL)) { 1428266077Sdes w += sldns_str_print(s, sl, "%s", protocol->p_name); 1429266077Sdes proto_name = protocol->p_name; 1430266077Sdes } else { 1431266077Sdes w += sldns_str_print(s, sl, "%u", (unsigned)protocol_nr); 1432266077Sdes } 1433266077Sdes 1434266077Sdes for(i=0; i<*dl; i++) { 1435266077Sdes if((*d)[i] == 0) 1436266077Sdes continue; 1437266077Sdes for(bit=0; bit<8; bit++) { 1438266077Sdes if(!(((*d)[i])&(0x80>>bit))) 1439266077Sdes continue; 1440266077Sdes port = (int)i*8 + bit; 1441266077Sdes 1442266077Sdes if(!print_symbols) 1443266077Sdes service = NULL; 1444266077Sdes else 1445266077Sdes service = getservbyport( 1446266077Sdes (int)htons((uint16_t)port), proto_name); 1447266077Sdes if(service && service->s_name) 1448266077Sdes w += sldns_str_print(s, sl, " %s", 1449266077Sdes service->s_name); 1450266077Sdes else w += sldns_str_print(s, sl, " %u", 1451266077Sdes (unsigned)port); 1452266077Sdes } 1453266077Sdes } 1454266077Sdes 1455266077Sdes#ifdef HAVE_ENDSERVENT 1456266077Sdes endservent(); 1457266077Sdes#endif 1458266077Sdes#ifdef HAVE_ENDPROTOENT 1459266077Sdes endprotoent(); 1460266077Sdes#endif 1461266077Sdes (*d) += *dl; 1462266077Sdes (*dl) = 0; 1463266077Sdes return w; 1464266077Sdes} 1465266077Sdes 1466266077Sdesint sldns_wire2str_nsap_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) 1467266077Sdes{ 1468266077Sdes return print_remainder_hex("0x", d, dl, s, sl); 1469266077Sdes} 1470266077Sdes 1471266077Sdesint sldns_wire2str_atma_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) 1472266077Sdes{ 1473266077Sdes return print_remainder_hex("", d, dl, s, sl); 1474266077Sdes} 1475266077Sdes 1476266077Sdes/* internal scan routine that can modify arguments on failure */ 1477266077Sdesstatic int sldns_wire2str_ipseckey_scan_internal(uint8_t** d, size_t* dl, 1478266077Sdes char** s, size_t* sl, uint8_t* pkt, size_t pktlen) 1479266077Sdes{ 1480266077Sdes /* http://www.ietf.org/internet-drafts/draft-ietf-ipseckey-rr-12.txt*/ 1481266077Sdes uint8_t precedence, gateway_type, algorithm; 1482266077Sdes int w = 0; 1483266077Sdes 1484266077Sdes if(*dl < 3) return -1; 1485266077Sdes precedence = (*d)[0]; 1486266077Sdes gateway_type = (*d)[1]; 1487266077Sdes algorithm = (*d)[2]; 1488266077Sdes if(gateway_type > 3) 1489266077Sdes return -1; /* unknown */ 1490266077Sdes (*d)+=3; 1491266077Sdes (*dl)-=3; 1492266077Sdes w += sldns_str_print(s, sl, "%d %d %d ", 1493266077Sdes (int)precedence, (int)gateway_type, (int)algorithm); 1494266077Sdes 1495266077Sdes switch(gateway_type) { 1496266077Sdes case 0: /* no gateway */ 1497266077Sdes w += sldns_str_print(s, sl, "."); 1498266077Sdes break; 1499266077Sdes case 1: /* ip4 */ 1500266077Sdes w += sldns_wire2str_a_scan(d, dl, s, sl); 1501266077Sdes break; 1502266077Sdes case 2: /* ip6 */ 1503266077Sdes w += sldns_wire2str_aaaa_scan(d, dl, s, sl); 1504266077Sdes break; 1505266077Sdes case 3: /* dname */ 1506266077Sdes w += sldns_wire2str_dname_scan(d, dl, s, sl, pkt, pktlen); 1507266077Sdes break; 1508266077Sdes default: /* unknown */ 1509266077Sdes return -1; 1510266077Sdes } 1511266077Sdes 1512266077Sdes if(*dl < 1) 1513266077Sdes return -1; 1514266077Sdes w += sldns_str_print(s, sl, " "); 1515266077Sdes w += sldns_wire2str_b64_scan_num(d, dl, s, sl, *dl); 1516266077Sdes return w; 1517266077Sdes} 1518266077Sdes 1519266077Sdesint sldns_wire2str_ipseckey_scan(uint8_t** d, size_t* dl, char** s, size_t* sl, 1520266077Sdes uint8_t* pkt, size_t pktlen) 1521266077Sdes{ 1522266077Sdes uint8_t* od = *d; 1523266077Sdes char* os = *s; 1524266077Sdes size_t odl = *dl, osl = *sl; 1525266077Sdes int w=sldns_wire2str_ipseckey_scan_internal(d, dl, s, sl, pkt, pktlen); 1526266077Sdes if(w == -1) { 1527266077Sdes *d = od; 1528266077Sdes *s = os; 1529266077Sdes *dl = odl; 1530266077Sdes *sl = osl; 1531266077Sdes return -1; 1532266077Sdes } 1533266077Sdes return w; 1534266077Sdes} 1535266077Sdes 1536266077Sdesint sldns_wire2str_hip_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) 1537266077Sdes{ 1538266077Sdes int w; 1539266077Sdes uint8_t algo, hitlen; 1540266077Sdes uint16_t pklen; 1541266077Sdes 1542266077Sdes /* read lengths */ 1543266077Sdes if(*dl < 4) 1544266077Sdes return -1; 1545266077Sdes hitlen = (*d)[0]; 1546266077Sdes algo = (*d)[1]; 1547266077Sdes pklen = sldns_read_uint16((*d)+2); 1548266077Sdes if(*dl < (size_t)4 + (size_t)hitlen + (size_t)pklen) 1549266077Sdes return -1; 1550266077Sdes 1551266077Sdes /* write: algo hit pubkey */ 1552266077Sdes w = sldns_str_print(s, sl, "%u ", (unsigned)algo); 1553266077Sdes w += print_hex_buf(s, sl, (*d)+4, hitlen); 1554266077Sdes w += sldns_str_print(s, sl, " "); 1555266077Sdes (*d)+=4+hitlen; 1556266077Sdes (*dl)-= (4+hitlen); 1557266077Sdes w += sldns_wire2str_b64_scan_num(d, dl, s, sl, pklen); 1558266077Sdes return w; 1559266077Sdes} 1560266077Sdes 1561266077Sdesint sldns_wire2str_int16_data_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) 1562266077Sdes{ 1563266077Sdes uint16_t n; 1564266077Sdes if(*dl < 2) 1565266077Sdes return -1; 1566266077Sdes n = sldns_read_uint16(*d); 1567266077Sdes if(*dl < 2+(size_t)n) 1568266077Sdes return -1; 1569266077Sdes (*d)+=2; 1570266077Sdes (*dl)-=2; 1571266077Sdes return sldns_wire2str_b64_scan_num(d, dl, s, sl, n); 1572266077Sdes} 1573266077Sdes 1574266077Sdesint sldns_wire2str_nsec3_next_owner_scan(uint8_t** d, size_t* dl, char** s, 1575266077Sdes size_t* sl) 1576266077Sdes{ 1577266077Sdes return sldns_wire2str_b32_ext_scan(d, dl, s, sl); 1578266077Sdes} 1579266077Sdes 1580266077Sdesint sldns_wire2str_ilnp64_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) 1581266077Sdes{ 1582266077Sdes int w; 1583266077Sdes if(*dl < 8) 1584266077Sdes return -1; 1585266077Sdes w = sldns_str_print(s, sl, "%.4x:%.4x:%.4x:%.4x", 1586266077Sdes sldns_read_uint16(*d), sldns_read_uint16((*d)+2), 1587266077Sdes sldns_read_uint16((*d)+4), sldns_read_uint16((*d)+6)); 1588266077Sdes (*d)+=8; 1589266077Sdes (*dl)-=8; 1590266077Sdes return w; 1591266077Sdes} 1592266077Sdes 1593266077Sdesint sldns_wire2str_eui48_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) 1594266077Sdes{ 1595266077Sdes int w; 1596266077Sdes if(*dl < 6) 1597266077Sdes return -1; 1598266077Sdes w = sldns_str_print(s, sl, "%.2x-%.2x-%.2x-%.2x-%.2x-%.2x", 1599266077Sdes (*d)[0], (*d)[1], (*d)[2], (*d)[3], (*d)[4], (*d)[5]); 1600266077Sdes (*d)+=6; 1601266077Sdes (*dl)-=6; 1602266077Sdes return w; 1603266077Sdes} 1604266077Sdes 1605266077Sdesint sldns_wire2str_eui64_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) 1606266077Sdes{ 1607266077Sdes int w; 1608266077Sdes if(*dl < 8) 1609266077Sdes return -1; 1610266077Sdes w = sldns_str_print(s, sl, "%.2x-%.2x-%.2x-%.2x-%.2x-%.2x-%.2x-%.2x", 1611266077Sdes (*d)[0], (*d)[1], (*d)[2], (*d)[3], (*d)[4], (*d)[5], 1612266077Sdes (*d)[6], (*d)[7]); 1613266077Sdes (*d)+=8; 1614266077Sdes (*dl)-=8; 1615266077Sdes return w; 1616266077Sdes} 1617266077Sdes 1618266077Sdesint sldns_wire2str_tag_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) 1619266077Sdes{ 1620266077Sdes size_t i, n; 1621266077Sdes int w = 0; 1622266077Sdes if(*dl < 1) 1623266077Sdes return -1; 1624266077Sdes n = (size_t)((*d)[0]); 1625266077Sdes if(*dl < 1+n) 1626266077Sdes return -1; 1627266077Sdes for(i=0; i<n; i++) 1628266077Sdes if(!isalnum((int)(*d)[i])) 1629266077Sdes return -1; 1630266077Sdes for(i=0; i<n; i++) 1631266077Sdes w += sldns_str_print(s, sl, "%c", (char)(*d)[i]); 1632266077Sdes (*d)+=n+1; 1633266077Sdes (*dl)-=(n+1); 1634266077Sdes return w; 1635266077Sdes} 1636266077Sdes 1637266077Sdesint sldns_wire2str_long_str_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) 1638266077Sdes{ 1639266077Sdes size_t i; 1640266077Sdes int w = 0; 1641266077Sdes w += sldns_str_print(s, sl, "\""); 1642266077Sdes for(i=0; i<*dl; i++) 1643266077Sdes w += str_char_print(s, sl, (*d)[i]); 1644266077Sdes w += sldns_str_print(s, sl, "\""); 1645266077Sdes (*d)+=*dl; 1646266077Sdes (*dl)=0; 1647266077Sdes return w; 1648266077Sdes} 1649266077Sdes 1650266077Sdesint sldns_wire2str_edns_llq_print(char** s, size_t* sl, uint8_t* data, 1651266077Sdes size_t len) 1652266077Sdes{ 1653266077Sdes /* LLQ constants */ 1654266077Sdes const char* llq_errors[] = {"NO-ERROR", "SERV-FULL", "STATIC", 1655266077Sdes "FORMAT-ERR", "NO-SUCH-LLQ", "BAD-VERS", "UNKNOWN_ERR"}; 1656266077Sdes const unsigned int llq_errors_num = 7; 1657266077Sdes const char* llq_opcodes[] = {"LLQ-SETUP", "LLQ-REFRESH", "LLQ-EVENT"}; 1658266077Sdes const unsigned int llq_opcodes_num = 3; 1659266077Sdes uint16_t version, llq_opcode, error_code; 1660266077Sdes uint64_t llq_id; 1661266077Sdes uint32_t lease_life; /* Requested or granted life of LLQ, in seconds */ 1662266077Sdes int w = 0; 1663266077Sdes 1664266077Sdes /* read the record */ 1665266077Sdes if(len != 18) { 1666266077Sdes w += sldns_str_print(s, sl, "malformed LLQ "); 1667266077Sdes w += print_hex_buf(s, sl, data, len); 1668266077Sdes return w; 1669266077Sdes } 1670266077Sdes version = sldns_read_uint16(data); 1671266077Sdes llq_opcode = sldns_read_uint16(data+2); 1672266077Sdes error_code = sldns_read_uint16(data+4); 1673266077Sdes memmove(&llq_id, data+6, sizeof(llq_id)); 1674266077Sdes lease_life = sldns_read_uint32(data+14); 1675266077Sdes 1676266077Sdes /* print it */ 1677266077Sdes w += sldns_str_print(s, sl, "v%d ", (int)version); 1678266077Sdes if(llq_opcode < llq_opcodes_num) 1679266077Sdes w += sldns_str_print(s, sl, "%s", llq_opcodes[llq_opcode]); 1680266077Sdes else w += sldns_str_print(s, sl, "opcode %d", (int)llq_opcode); 1681266077Sdes if(error_code < llq_errors_num) 1682266077Sdes w += sldns_str_print(s, sl, " %s", llq_errors[error_code]); 1683266077Sdes else w += sldns_str_print(s, sl, " error %d", (int)error_code); 1684266077Sdes#ifndef USE_WINSOCK 1685266077Sdes w += sldns_str_print(s, sl, " id %llx lease-life %lu", 1686266077Sdes (unsigned long long)llq_id, (unsigned long)lease_life); 1687266077Sdes#else 1688266077Sdes w += sldns_str_print(s, sl, " id %I64x lease-life %lu", 1689266077Sdes (unsigned long long)llq_id, (unsigned long)lease_life); 1690266077Sdes#endif 1691266077Sdes return w; 1692266077Sdes} 1693266077Sdes 1694266077Sdesint sldns_wire2str_edns_ul_print(char** s, size_t* sl, uint8_t* data, 1695266077Sdes size_t len) 1696266077Sdes{ 1697266077Sdes uint32_t lease; 1698266077Sdes int w = 0; 1699266077Sdes if(len != 4) { 1700266077Sdes w += sldns_str_print(s, sl, "malformed UL "); 1701266077Sdes w += print_hex_buf(s, sl, data, len); 1702266077Sdes return w; 1703266077Sdes } 1704266077Sdes lease = sldns_read_uint32(data); 1705266077Sdes w += sldns_str_print(s, sl, "lease %lu", (unsigned long)lease); 1706266077Sdes return w; 1707266077Sdes} 1708266077Sdes 1709266077Sdesint sldns_wire2str_edns_nsid_print(char** s, size_t* sl, uint8_t* data, 1710266077Sdes size_t len) 1711266077Sdes{ 1712266077Sdes int w = 0; 1713266077Sdes size_t i, printed=0; 1714266077Sdes w += print_hex_buf(s, sl, data, len); 1715266077Sdes for(i=0; i<len; i++) { 1716266077Sdes if(isprint((int)data[i]) || data[i] == '\t') { 1717266077Sdes if(!printed) { 1718266077Sdes w += sldns_str_print(s, sl, " ("); 1719266077Sdes printed = 1; 1720266077Sdes } 1721266077Sdes w += sldns_str_print(s, sl, "%c", (char)data[i]); 1722266077Sdes } 1723266077Sdes } 1724266077Sdes if(printed) 1725266077Sdes w += sldns_str_print(s, sl, ")"); 1726266077Sdes return w; 1727266077Sdes} 1728266077Sdes 1729266077Sdesint sldns_wire2str_edns_dau_print(char** s, size_t* sl, uint8_t* data, 1730266077Sdes size_t len) 1731266077Sdes{ 1732266077Sdes sldns_lookup_table *lt; 1733266077Sdes size_t i; 1734266077Sdes int w = 0; 1735266077Sdes for(i=0; i<len; i++) { 1736266077Sdes lt = sldns_lookup_by_id(sldns_algorithms, (int)data[i]); 1737266077Sdes if(lt && lt->name) 1738266077Sdes w += sldns_str_print(s, sl, " %s", lt->name); 1739266077Sdes else w += sldns_str_print(s, sl, " %d", (int)data[i]); 1740266077Sdes } 1741266077Sdes return w; 1742266077Sdes} 1743266077Sdes 1744266077Sdesint sldns_wire2str_edns_dhu_print(char** s, size_t* sl, uint8_t* data, 1745266077Sdes size_t len) 1746266077Sdes{ 1747266077Sdes sldns_lookup_table *lt; 1748266077Sdes size_t i; 1749266077Sdes int w = 0; 1750266077Sdes for(i=0; i<len; i++) { 1751266077Sdes lt = sldns_lookup_by_id(sldns_hashes, (int)data[i]); 1752266077Sdes if(lt && lt->name) 1753266077Sdes w += sldns_str_print(s, sl, " %s", lt->name); 1754266077Sdes else w += sldns_str_print(s, sl, " %d", (int)data[i]); 1755266077Sdes } 1756266077Sdes return w; 1757266077Sdes} 1758266077Sdes 1759266077Sdesint sldns_wire2str_edns_n3u_print(char** s, size_t* sl, uint8_t* data, 1760266077Sdes size_t len) 1761266077Sdes{ 1762266077Sdes size_t i; 1763266077Sdes int w = 0; 1764266077Sdes for(i=0; i<len; i++) { 1765266077Sdes if(data[i] == 1) 1766266077Sdes w += sldns_str_print(s, sl, " SHA1"); 1767266077Sdes else w += sldns_str_print(s, sl, " %d", (int)data[i]); 1768266077Sdes } 1769266077Sdes return w; 1770266077Sdes} 1771266077Sdes 1772266077Sdesint sldns_wire2str_edns_subnet_print(char** s, size_t* sl, uint8_t* data, 1773266077Sdes size_t len) 1774266077Sdes{ 1775266077Sdes int w = 0; 1776266077Sdes uint16_t family; 1777266077Sdes uint8_t source, scope; 1778266077Sdes if(len < 4) { 1779266077Sdes w += sldns_str_print(s, sl, "malformed subnet "); 1780266077Sdes w += print_hex_buf(s, sl, data, len); 1781266077Sdes return w; 1782266077Sdes } 1783266077Sdes family = sldns_read_uint16(data); 1784266077Sdes source = data[2]; 1785266077Sdes scope = data[3]; 1786266077Sdes if(family == 1) { 1787266077Sdes /* IP4 */ 1788266077Sdes char buf[64]; 1789266077Sdes uint8_t ip4[4]; 1790266077Sdes memset(ip4, 0, sizeof(ip4)); 1791266077Sdes if(len-4 > 4) { 1792266077Sdes w += sldns_str_print(s, sl, "trailingdata:"); 1793266077Sdes w += print_hex_buf(s, sl, data+4+4, len-4-4); 1794266077Sdes w += sldns_str_print(s, sl, " "); 1795266077Sdes len = 4+4; 1796266077Sdes } 1797266077Sdes memmove(ip4, data+4, len-4); 1798266077Sdes if(!inet_ntop(AF_INET, ip4, buf, (socklen_t)sizeof(buf))) { 1799266077Sdes w += sldns_str_print(s, sl, "ip4ntoperror "); 1800266077Sdes w += print_hex_buf(s, sl, data+4+4, len-4-4); 1801266077Sdes } else { 1802266077Sdes w += sldns_str_print(s, sl, "%s", buf); 1803266077Sdes } 1804266077Sdes } else if(family == 2) { 1805266077Sdes /* IP6 */ 1806266077Sdes char buf[64]; 1807266077Sdes uint8_t ip6[16]; 1808266077Sdes memset(ip6, 0, sizeof(ip6)); 1809266077Sdes if(len-4 > 16) { 1810266077Sdes w += sldns_str_print(s, sl, "trailingdata:"); 1811266077Sdes w += print_hex_buf(s, sl, data+4+16, len-4-16); 1812266077Sdes w += sldns_str_print(s, sl, " "); 1813266077Sdes len = 4+16; 1814266077Sdes } 1815266077Sdes memmove(ip6, data+4, len-4); 1816266077Sdes#ifdef AF_INET6 1817266077Sdes if(!inet_ntop(AF_INET6, ip6, buf, (socklen_t)sizeof(buf))) { 1818266077Sdes w += sldns_str_print(s, sl, "ip6ntoperror "); 1819266077Sdes w += print_hex_buf(s, sl, data+4+4, len-4-4); 1820266077Sdes } else { 1821266077Sdes w += sldns_str_print(s, sl, "%s", buf); 1822266077Sdes } 1823266077Sdes#else 1824266077Sdes w += print_hex_buf(s, sl, data+4+4, len-4-4); 1825266077Sdes#endif 1826266077Sdes } else { 1827266077Sdes /* unknown */ 1828266077Sdes w += sldns_str_print(s, sl, "family %d ", 1829266077Sdes (int)family); 1830266077Sdes w += print_hex_buf(s, sl, data, len); 1831266077Sdes } 1832266077Sdes w += sldns_str_print(s, sl, "/%d scope /%d", (int)source, (int)scope); 1833266077Sdes return w; 1834266077Sdes} 1835266077Sdes 1836266077Sdesint sldns_wire2str_edns_option_print(char** s, size_t* sl, 1837266077Sdes uint16_t option_code, uint8_t* optdata, size_t optlen) 1838266077Sdes{ 1839266077Sdes int w = 0; 1840266077Sdes w += sldns_wire2str_edns_option_code_print(s, sl, option_code); 1841266077Sdes w += sldns_str_print(s, sl, ": "); 1842266077Sdes switch(option_code) { 1843266077Sdes case LDNS_EDNS_LLQ: 1844266077Sdes w += sldns_wire2str_edns_llq_print(s, sl, optdata, optlen); 1845266077Sdes break; 1846266077Sdes case LDNS_EDNS_UL: 1847266077Sdes w += sldns_wire2str_edns_ul_print(s, sl, optdata, optlen); 1848266077Sdes break; 1849266077Sdes case LDNS_EDNS_NSID: 1850266077Sdes w += sldns_wire2str_edns_nsid_print(s, sl, optdata, optlen); 1851266077Sdes break; 1852266077Sdes case LDNS_EDNS_DAU: 1853266077Sdes w += sldns_wire2str_edns_dau_print(s, sl, optdata, optlen); 1854266077Sdes break; 1855266077Sdes case LDNS_EDNS_DHU: 1856266077Sdes w += sldns_wire2str_edns_dhu_print(s, sl, optdata, optlen); 1857266077Sdes break; 1858266077Sdes case LDNS_EDNS_N3U: 1859266077Sdes w += sldns_wire2str_edns_n3u_print(s, sl, optdata, optlen); 1860266077Sdes break; 1861266077Sdes case LDNS_EDNS_CLIENT_SUBNET: 1862266077Sdes w += sldns_wire2str_edns_subnet_print(s, sl, optdata, optlen); 1863266077Sdes break; 1864266077Sdes default: 1865266077Sdes /* unknown option code */ 1866266077Sdes w += print_hex_buf(s, sl, optdata, optlen); 1867266077Sdes break; 1868266077Sdes } 1869266077Sdes return w; 1870266077Sdes} 1871266077Sdes 1872266077Sdes/** print the edns options to string */ 1873266077Sdesstatic int 1874266077Sdesprint_edns_opts(char** s, size_t* sl, uint8_t* rdata, size_t rdatalen) 1875266077Sdes{ 1876266077Sdes uint16_t option_code, option_len; 1877266077Sdes int w = 0; 1878266077Sdes while(rdatalen > 0) { 1879266077Sdes /* option name */ 1880266077Sdes if(rdatalen < 4) { 1881266077Sdes w += sldns_str_print(s, sl, " ; malformed: "); 1882266077Sdes w += print_hex_buf(s, sl, rdata, rdatalen); 1883266077Sdes return w; 1884266077Sdes } 1885266077Sdes option_code = sldns_read_uint16(rdata); 1886266077Sdes option_len = sldns_read_uint16(rdata+2); 1887266077Sdes rdata += 4; 1888266077Sdes rdatalen -= 4; 1889266077Sdes 1890266077Sdes /* option value */ 1891266077Sdes if(rdatalen < (size_t)option_len) { 1892266077Sdes w += sldns_str_print(s, sl, " ; malformed "); 1893266077Sdes w += sldns_wire2str_edns_option_code_print(s, sl, 1894266077Sdes option_code); 1895266077Sdes w += sldns_str_print(s, sl, ": "); 1896266077Sdes w += print_hex_buf(s, sl, rdata, rdatalen); 1897266077Sdes return w; 1898266077Sdes } 1899266077Sdes w += sldns_str_print(s, sl, " ; "); 1900266077Sdes w += sldns_wire2str_edns_option_print(s, sl, option_code, 1901266077Sdes rdata, option_len); 1902266077Sdes rdata += option_len; 1903266077Sdes rdatalen -= option_len; 1904266077Sdes } 1905266077Sdes return w; 1906266077Sdes} 1907266077Sdes 1908266077Sdesint sldns_wire2str_edns_scan(uint8_t** data, size_t* data_len, char** str, 1909266077Sdes size_t* str_len, uint8_t* pkt, size_t pktlen) 1910266077Sdes{ 1911266077Sdes int w = 0; 1912266077Sdes uint8_t ext_rcode, edns_version; 1913266077Sdes uint16_t udpsize, edns_bits, rdatalen; 1914266077Sdes w += sldns_str_print(str, str_len, "; EDNS:"); 1915266077Sdes 1916266077Sdes /* some input checks, domain name */ 1917266077Sdes if(*data_len < 1+10) 1918266077Sdes return w + print_remainder_hex("Error malformed 0x", 1919266077Sdes data, data_len, str, str_len); 1920266077Sdes if(*data[0] != 0) { 1921266077Sdes return w + print_remainder_hex("Error nonrootdname 0x", 1922266077Sdes data, data_len, str, str_len); 1923266077Sdes } 1924266077Sdes (*data)++; 1925266077Sdes (*data_len)--; 1926266077Sdes 1927266077Sdes /* check type and read fixed contents */ 1928266077Sdes if(sldns_read_uint16((*data)) != LDNS_RR_TYPE_OPT) { 1929266077Sdes return w + print_remainder_hex("Error nottypeOPT 0x", 1930266077Sdes data, data_len, str, str_len); 1931266077Sdes } 1932266077Sdes udpsize = sldns_read_uint16((*data)+2); 1933266077Sdes ext_rcode = (*data)[4]; 1934266077Sdes edns_version = (*data)[5]; 1935266077Sdes edns_bits = sldns_read_uint16((*data)+6); 1936266077Sdes rdatalen = sldns_read_uint16((*data)+8); 1937266077Sdes (*data)+=10; 1938266077Sdes (*data_len)-=10; 1939266077Sdes 1940266077Sdes w += sldns_str_print(str, str_len, " version: %u;", 1941266077Sdes (unsigned)edns_version); 1942266077Sdes w += sldns_str_print(str, str_len, " flags:"); 1943266077Sdes if((edns_bits & LDNS_EDNS_MASK_DO_BIT)) 1944266077Sdes w += sldns_str_print(str, str_len, " do"); 1945266077Sdes /* the extended rcode is the value set, shifted four bits, 1946266077Sdes * and or'd with the original rcode */ 1947266077Sdes if(ext_rcode) { 1948266077Sdes int rc = ((int)ext_rcode)<<4; 1949266077Sdes if(pkt && pktlen >= LDNS_HEADER_SIZE) 1950266077Sdes rc |= LDNS_RCODE_WIRE(pkt); 1951266077Sdes w += sldns_str_print(str, str_len, " ; ext-rcode: %d", rc); 1952266077Sdes } 1953266077Sdes w += sldns_str_print(str, str_len, " ; udp: %u", (unsigned)udpsize); 1954266077Sdes 1955266077Sdes if(rdatalen) { 1956266077Sdes if(*data_len < rdatalen) { 1957266077Sdes w += sldns_str_print(str, str_len, 1958266077Sdes " ; Error EDNS rdata too short; "); 1959266077Sdes rdatalen = *data_len; 1960266077Sdes } 1961266077Sdes w += print_edns_opts(str, str_len, *data, rdatalen); 1962266077Sdes (*data) += rdatalen; 1963266077Sdes (*data_len) -= rdatalen; 1964266077Sdes } 1965266077Sdes w += sldns_str_print(str, str_len, "\n"); 1966266077Sdes return w; 1967266077Sdes} 1968