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" 18287915Sdes#include "sldns/wire2str.h" 19287915Sdes#include "sldns/str2wire.h" 20287915Sdes#include "sldns/rrdef.h" 21287915Sdes#include "sldns/pkthdr.h" 22287915Sdes#include "sldns/parseutil.h" 23287915Sdes#include "sldns/sbuffer.h" 24287915Sdes#include "sldns/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 } 700292206Sdes if(*dlen != 0) { 701292206Sdes goto failed; 702292206Sdes } 703266077Sdes return w; 704266077Sdes} 705266077Sdes 706266077Sdesint sldns_wire2str_rdata_unknown_scan(uint8_t** d, size_t* dlen, char** s, 707266077Sdes size_t* slen) 708266077Sdes{ 709266077Sdes int w = 0; 710266077Sdes 711266077Sdes /* print length */ 712266077Sdes w += sldns_str_print(s, slen, "\\# %u", (unsigned)*dlen); 713266077Sdes 714266077Sdes /* print rdlen in hex */ 715266077Sdes if(*dlen != 0) 716266077Sdes w += sldns_str_print(s, slen, " "); 717266077Sdes w += print_hex_buf(s, slen, *d, *dlen); 718266077Sdes (*d) += *dlen; 719266077Sdes (*dlen) = 0; 720266077Sdes return w; 721266077Sdes} 722266077Sdes 723266077Sdes/** print and escape one character for a domain dname */ 724266077Sdesstatic int dname_char_print(char** s, size_t* slen, uint8_t c) 725266077Sdes{ 726266077Sdes if(c == '.' || c == ';' || c == '(' || c == ')' || c == '\\') 727266077Sdes return sldns_str_print(s, slen, "\\%c", c); 728276541Sdes else if(!(isascii((unsigned char)c) && isgraph((unsigned char)c))) 729266077Sdes return sldns_str_print(s, slen, "\\%03u", (unsigned)c); 730266077Sdes /* plain printout */ 731266077Sdes if(*slen) { 732266077Sdes **s = (char)c; 733266077Sdes (*s)++; 734266077Sdes (*slen)--; 735266077Sdes } 736266077Sdes return 1; 737266077Sdes} 738266077Sdes 739266077Sdesint sldns_wire2str_dname_scan(uint8_t** d, size_t* dlen, char** s, size_t* slen, 740266077Sdes uint8_t* pkt, size_t pktlen) 741266077Sdes{ 742266077Sdes int w = 0; 743266077Sdes /* spool labels onto the string, use compression if its there */ 744266077Sdes uint8_t* pos = *d; 745266077Sdes unsigned i, counter=0; 746266077Sdes const unsigned maxcompr = 1000; /* loop detection, max compr ptrs */ 747266077Sdes int in_buf = 1; 748266077Sdes if(*dlen == 0) return sldns_str_print(s, slen, "ErrorMissingDname"); 749266077Sdes if(*pos == 0) { 750266077Sdes (*d)++; 751266077Sdes (*dlen)--; 752266077Sdes return sldns_str_print(s, slen, "."); 753266077Sdes } 754266077Sdes while(*pos) { 755266077Sdes /* read label length */ 756266077Sdes uint8_t labellen = *pos++; 757266077Sdes if(in_buf) { (*d)++; (*dlen)--; } 758266077Sdes 759266077Sdes /* find out what sort of label we have */ 760266077Sdes if((labellen&0xc0) == 0xc0) { 761266077Sdes /* compressed */ 762266077Sdes uint16_t target = 0; 763266077Sdes if(in_buf && *dlen == 0) 764266077Sdes return w + sldns_str_print(s, slen, 765266077Sdes "ErrorPartialDname"); 766266077Sdes else if(!in_buf && pos+1 > pkt+pktlen) 767266077Sdes return w + sldns_str_print(s, slen, 768266077Sdes "ErrorPartialDname"); 769266077Sdes target = ((labellen&0x3f)<<8) | *pos; 770266077Sdes if(in_buf) { (*d)++; (*dlen)--; } 771266077Sdes /* move to target, if possible */ 772266077Sdes if(!pkt || target >= pktlen) 773266077Sdes return w + sldns_str_print(s, slen, 774266077Sdes "ErrorComprPtrOutOfBounds"); 775266077Sdes if(counter++ > maxcompr) 776266077Sdes return w + sldns_str_print(s, slen, 777266077Sdes "ErrorComprPtrLooped"); 778266077Sdes in_buf = 0; 779266077Sdes pos = pkt+target; 780266077Sdes continue; 781266077Sdes } else if((labellen&0xc0)) { 782266077Sdes /* notimpl label type */ 783266077Sdes w += sldns_str_print(s, slen, 784266077Sdes "ErrorLABELTYPE%xIsUnknown", 785266077Sdes (int)(labellen&0xc0)); 786266077Sdes return w; 787266077Sdes } 788266077Sdes 789266077Sdes /* spool label characters, end with '.' */ 790266077Sdes if(in_buf && *dlen < labellen) labellen = *dlen; 791266077Sdes else if(!in_buf && pos+labellen > pkt+pktlen) 792266077Sdes labellen = (uint8_t)(pkt + pktlen - pos); 793266077Sdes for(i=0; i<(unsigned)labellen; i++) { 794266077Sdes w += dname_char_print(s, slen, *pos++); 795266077Sdes } 796266077Sdes if(in_buf) { 797266077Sdes (*d) += labellen; 798266077Sdes (*dlen) -= labellen; 799266077Sdes if(*dlen == 0) break; 800266077Sdes } 801266077Sdes w += sldns_str_print(s, slen, "."); 802266077Sdes } 803266077Sdes /* skip over final root label */ 804266077Sdes if(in_buf && *dlen > 0) { (*d)++; (*dlen)--; } 805266077Sdes /* in case we printed no labels, terminate dname */ 806266077Sdes if(w == 0) w += sldns_str_print(s, slen, "."); 807266077Sdes return w; 808266077Sdes} 809266077Sdes 810266077Sdesint sldns_wire2str_opcode_print(char** s, size_t* slen, int opcode) 811266077Sdes{ 812266077Sdes sldns_lookup_table *lt = sldns_lookup_by_id(sldns_opcodes, opcode); 813266077Sdes if (lt && lt->name) { 814266077Sdes return sldns_str_print(s, slen, "%s", lt->name); 815266077Sdes } 816266077Sdes return sldns_str_print(s, slen, "OPCODE%u", (unsigned)opcode); 817266077Sdes} 818266077Sdes 819266077Sdesint sldns_wire2str_rcode_print(char** s, size_t* slen, int rcode) 820266077Sdes{ 821266077Sdes sldns_lookup_table *lt = sldns_lookup_by_id(sldns_rcodes, rcode); 822266077Sdes if (lt && lt->name) { 823266077Sdes return sldns_str_print(s, slen, "%s", lt->name); 824266077Sdes } 825266077Sdes return sldns_str_print(s, slen, "RCODE%u", (unsigned)rcode); 826266077Sdes} 827266077Sdes 828266077Sdesint sldns_wire2str_class_print(char** s, size_t* slen, uint16_t rrclass) 829266077Sdes{ 830266077Sdes sldns_lookup_table *lt = sldns_lookup_by_id(sldns_rr_classes, 831266077Sdes (int)rrclass); 832266077Sdes if (lt && lt->name) { 833266077Sdes return sldns_str_print(s, slen, "%s", lt->name); 834266077Sdes } 835266077Sdes return sldns_str_print(s, slen, "CLASS%u", (unsigned)rrclass); 836266077Sdes} 837266077Sdes 838266077Sdesint sldns_wire2str_type_print(char** s, size_t* slen, uint16_t rrtype) 839266077Sdes{ 840266077Sdes const sldns_rr_descriptor *descriptor = sldns_rr_descript(rrtype); 841266077Sdes if (descriptor && descriptor->_name) { 842266077Sdes return sldns_str_print(s, slen, "%s", descriptor->_name); 843266077Sdes } 844266077Sdes return sldns_str_print(s, slen, "TYPE%u", (unsigned)rrtype); 845266077Sdes} 846266077Sdes 847266077Sdesint sldns_wire2str_edns_option_code_print(char** s, size_t* slen, 848266077Sdes uint16_t opcode) 849266077Sdes{ 850266077Sdes sldns_lookup_table *lt = sldns_lookup_by_id(sldns_edns_options, 851266077Sdes (int)opcode); 852266077Sdes if (lt && lt->name) { 853266077Sdes return sldns_str_print(s, slen, "%s", lt->name); 854266077Sdes } 855266077Sdes return sldns_str_print(s, slen, "OPT%u", (unsigned)opcode); 856266077Sdes} 857266077Sdes 858266077Sdesint sldns_wire2str_class_scan(uint8_t** d, size_t* dlen, char** s, size_t* slen) 859266077Sdes{ 860266077Sdes uint16_t c; 861266077Sdes if(*dlen == 0) return 0; 862266077Sdes if(*dlen < 2) return print_remainder_hex("Error malformed 0x", d, dlen, s, slen); 863266077Sdes c = sldns_read_uint16(*d); 864266077Sdes (*d)+=2; 865266077Sdes (*dlen)-=2; 866266077Sdes return sldns_wire2str_class_print(s, slen, c); 867266077Sdes} 868266077Sdes 869266077Sdesint sldns_wire2str_type_scan(uint8_t** d, size_t* dlen, char** s, size_t* slen) 870266077Sdes{ 871266077Sdes uint16_t t; 872266077Sdes if(*dlen == 0) return 0; 873266077Sdes if(*dlen < 2) return print_remainder_hex("Error malformed 0x", d, dlen, s, slen); 874266077Sdes t = sldns_read_uint16(*d); 875266077Sdes (*d)+=2; 876266077Sdes (*dlen)-=2; 877266077Sdes return sldns_wire2str_type_print(s, slen, t); 878266077Sdes} 879266077Sdes 880266077Sdesint sldns_wire2str_ttl_scan(uint8_t** d, size_t* dlen, char** s, size_t* slen) 881266077Sdes{ 882266077Sdes uint32_t ttl; 883266077Sdes if(*dlen == 0) return 0; 884266077Sdes if(*dlen < 4) return print_remainder_hex("Error malformed 0x", d, dlen, s, slen); 885266077Sdes ttl = sldns_read_uint32(*d); 886266077Sdes (*d)+=4; 887266077Sdes (*dlen)-=4; 888266077Sdes return sldns_str_print(s, slen, "%u", (unsigned)ttl); 889266077Sdes} 890266077Sdes 891266077Sdesint sldns_wire2str_rdf_scan(uint8_t** d, size_t* dlen, char** s, size_t* slen, 892266077Sdes int rdftype, uint8_t* pkt, size_t pktlen) 893266077Sdes{ 894266077Sdes if(*dlen == 0) return 0; 895266077Sdes switch(rdftype) { 896266077Sdes case LDNS_RDF_TYPE_NONE: 897266077Sdes return 0; 898266077Sdes case LDNS_RDF_TYPE_DNAME: 899266077Sdes return sldns_wire2str_dname_scan(d, dlen, s, slen, pkt, pktlen); 900266077Sdes case LDNS_RDF_TYPE_INT8: 901266077Sdes return sldns_wire2str_int8_scan(d, dlen, s, slen); 902266077Sdes case LDNS_RDF_TYPE_INT16: 903266077Sdes return sldns_wire2str_int16_scan(d, dlen, s, slen); 904266077Sdes case LDNS_RDF_TYPE_INT32: 905266077Sdes return sldns_wire2str_int32_scan(d, dlen, s, slen); 906266077Sdes case LDNS_RDF_TYPE_PERIOD: 907266077Sdes return sldns_wire2str_period_scan(d, dlen, s, slen); 908266077Sdes case LDNS_RDF_TYPE_TSIGTIME: 909266077Sdes return sldns_wire2str_tsigtime_scan(d, dlen, s, slen); 910266077Sdes case LDNS_RDF_TYPE_A: 911266077Sdes return sldns_wire2str_a_scan(d, dlen, s, slen); 912266077Sdes case LDNS_RDF_TYPE_AAAA: 913266077Sdes return sldns_wire2str_aaaa_scan(d, dlen, s, slen); 914266077Sdes case LDNS_RDF_TYPE_STR: 915266077Sdes return sldns_wire2str_str_scan(d, dlen, s, slen); 916266077Sdes case LDNS_RDF_TYPE_APL: 917266077Sdes return sldns_wire2str_apl_scan(d, dlen, s, slen); 918266077Sdes case LDNS_RDF_TYPE_B32_EXT: 919266077Sdes return sldns_wire2str_b32_ext_scan(d, dlen, s, slen); 920266077Sdes case LDNS_RDF_TYPE_B64: 921266077Sdes return sldns_wire2str_b64_scan(d, dlen, s, slen); 922266077Sdes case LDNS_RDF_TYPE_HEX: 923266077Sdes return sldns_wire2str_hex_scan(d, dlen, s, slen); 924266077Sdes case LDNS_RDF_TYPE_NSEC: 925266077Sdes return sldns_wire2str_nsec_scan(d, dlen, s, slen); 926266077Sdes case LDNS_RDF_TYPE_NSEC3_SALT: 927266077Sdes return sldns_wire2str_nsec3_salt_scan(d, dlen, s, slen); 928266077Sdes case LDNS_RDF_TYPE_TYPE: 929266077Sdes return sldns_wire2str_type_scan(d, dlen, s, slen); 930266077Sdes case LDNS_RDF_TYPE_CLASS: 931266077Sdes return sldns_wire2str_class_scan(d, dlen, s, slen); 932266077Sdes case LDNS_RDF_TYPE_CERT_ALG: 933266077Sdes return sldns_wire2str_cert_alg_scan(d, dlen, s, slen); 934266077Sdes case LDNS_RDF_TYPE_ALG: 935266077Sdes return sldns_wire2str_alg_scan(d, dlen, s, slen); 936266077Sdes case LDNS_RDF_TYPE_UNKNOWN: 937266077Sdes return sldns_wire2str_unknown_scan(d, dlen, s, slen); 938266077Sdes case LDNS_RDF_TYPE_TIME: 939266077Sdes return sldns_wire2str_time_scan(d, dlen, s, slen); 940266077Sdes case LDNS_RDF_TYPE_LOC: 941266077Sdes return sldns_wire2str_loc_scan(d, dlen, s, slen); 942266077Sdes case LDNS_RDF_TYPE_WKS: 943266077Sdes case LDNS_RDF_TYPE_SERVICE: 944266077Sdes return sldns_wire2str_wks_scan(d, dlen, s, slen); 945266077Sdes case LDNS_RDF_TYPE_NSAP: 946266077Sdes return sldns_wire2str_nsap_scan(d, dlen, s, slen); 947266077Sdes case LDNS_RDF_TYPE_ATMA: 948266077Sdes return sldns_wire2str_atma_scan(d, dlen, s, slen); 949266077Sdes case LDNS_RDF_TYPE_IPSECKEY: 950266077Sdes return sldns_wire2str_ipseckey_scan(d, dlen, s, slen, pkt, 951266077Sdes pktlen); 952266077Sdes case LDNS_RDF_TYPE_HIP: 953266077Sdes return sldns_wire2str_hip_scan(d, dlen, s, slen); 954266077Sdes case LDNS_RDF_TYPE_INT16_DATA: 955266077Sdes return sldns_wire2str_int16_data_scan(d, dlen, s, slen); 956266077Sdes case LDNS_RDF_TYPE_NSEC3_NEXT_OWNER: 957266077Sdes return sldns_wire2str_b32_ext_scan(d, dlen, s, slen); 958266077Sdes case LDNS_RDF_TYPE_ILNP64: 959266077Sdes return sldns_wire2str_ilnp64_scan(d, dlen, s, slen); 960266077Sdes case LDNS_RDF_TYPE_EUI48: 961266077Sdes return sldns_wire2str_eui48_scan(d, dlen, s, slen); 962266077Sdes case LDNS_RDF_TYPE_EUI64: 963266077Sdes return sldns_wire2str_eui64_scan(d, dlen, s, slen); 964266077Sdes case LDNS_RDF_TYPE_TAG: 965266077Sdes return sldns_wire2str_tag_scan(d, dlen, s, slen); 966266077Sdes case LDNS_RDF_TYPE_LONG_STR: 967266077Sdes return sldns_wire2str_long_str_scan(d, dlen, s, slen); 968266077Sdes } 969266077Sdes /* unknown rdf type */ 970266077Sdes return -1; 971266077Sdes} 972266077Sdes 973266077Sdesint sldns_wire2str_int8_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) 974266077Sdes{ 975266077Sdes int w; 976266077Sdes if(*dl < 1) return -1; 977266077Sdes w = sldns_str_print(s, sl, "%u", (unsigned)**d); 978266077Sdes (*d)++; 979266077Sdes (*dl)--; 980266077Sdes return w; 981266077Sdes} 982266077Sdes 983266077Sdesint sldns_wire2str_int16_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) 984266077Sdes{ 985266077Sdes int w; 986266077Sdes if(*dl < 2) return -1; 987266077Sdes w = sldns_str_print(s, sl, "%lu", (unsigned long)sldns_read_uint16(*d)); 988266077Sdes (*d)+=2; 989266077Sdes (*dl)-=2; 990266077Sdes return w; 991266077Sdes} 992266077Sdes 993266077Sdesint sldns_wire2str_int32_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) 994266077Sdes{ 995266077Sdes int w; 996266077Sdes if(*dl < 4) return -1; 997266077Sdes w = sldns_str_print(s, sl, "%lu", (unsigned long)sldns_read_uint32(*d)); 998266077Sdes (*d)+=4; 999266077Sdes (*dl)-=4; 1000266077Sdes return w; 1001266077Sdes} 1002266077Sdes 1003266077Sdesint sldns_wire2str_period_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) 1004266077Sdes{ 1005266077Sdes int w; 1006266077Sdes if(*dl < 4) return -1; 1007266077Sdes w = sldns_str_print(s, sl, "%u", (unsigned)sldns_read_uint32(*d)); 1008266077Sdes (*d)+=4; 1009266077Sdes (*dl)-=4; 1010266077Sdes return w; 1011266077Sdes} 1012266077Sdes 1013266077Sdesint sldns_wire2str_tsigtime_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) 1014266077Sdes{ 1015266077Sdes /* tsigtime is 48 bits network order unsigned integer */ 1016266077Sdes int w; 1017266077Sdes uint64_t tsigtime = 0; 1018266077Sdes uint64_t d0, d1, d2, d3, d4, d5; 1019266077Sdes if(*dl < 6) return -1; 1020266077Sdes d0 = (*d)[0]; /* cast to uint64 for shift operations */ 1021266077Sdes d1 = (*d)[1]; 1022266077Sdes d2 = (*d)[2]; 1023266077Sdes d3 = (*d)[3]; 1024266077Sdes d4 = (*d)[4]; 1025266077Sdes d5 = (*d)[5]; 1026266077Sdes tsigtime = (d0<<40) | (d1<<32) | (d2<<24) | (d3<<16) | (d4<<8) | d5; 1027266077Sdes#ifndef USE_WINSOCK 1028266077Sdes w = sldns_str_print(s, sl, "%llu", (long long)tsigtime); 1029266077Sdes#else 1030266077Sdes w = sldns_str_print(s, sl, "%I64u", (long long)tsigtime); 1031266077Sdes#endif 1032266077Sdes (*d)+=6; 1033266077Sdes (*dl)-=6; 1034266077Sdes return w; 1035266077Sdes} 1036266077Sdes 1037266077Sdesint sldns_wire2str_a_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) 1038266077Sdes{ 1039266077Sdes char buf[32]; 1040266077Sdes int w; 1041266077Sdes if(*dl < 4) return -1; 1042266077Sdes if(!inet_ntop(AF_INET, *d, buf, (socklen_t)sizeof(buf))) 1043266077Sdes return -1; 1044266077Sdes w = sldns_str_print(s, sl, "%s", buf); 1045266077Sdes (*d)+=4; 1046266077Sdes (*dl)-=4; 1047266077Sdes return w; 1048266077Sdes} 1049266077Sdes 1050266077Sdesint sldns_wire2str_aaaa_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) 1051266077Sdes{ 1052266077Sdes#ifdef AF_INET6 1053266077Sdes char buf[64]; 1054266077Sdes int w; 1055266077Sdes if(*dl < 16) return -1; 1056266077Sdes if(!inet_ntop(AF_INET6, *d, buf, (socklen_t)sizeof(buf))) 1057266077Sdes return -1; 1058266077Sdes w = sldns_str_print(s, sl, "%s", buf); 1059266077Sdes (*d)+=16; 1060266077Sdes (*dl)-=16; 1061266077Sdes return w; 1062266077Sdes#else 1063266077Sdes return -1; 1064266077Sdes#endif 1065266077Sdes} 1066266077Sdes 1067266077Sdes/** printout escaped TYPE_STR character */ 1068266077Sdesstatic int str_char_print(char** s, size_t* sl, uint8_t c) 1069266077Sdes{ 1070276541Sdes if(isprint((unsigned char)c) || c == '\t') { 1071266077Sdes if(c == '\"' || c == '\\') 1072266077Sdes return sldns_str_print(s, sl, "\\%c", c); 1073266077Sdes if(*sl) { 1074266077Sdes **s = (char)c; 1075266077Sdes (*s)++; 1076266077Sdes (*sl)--; 1077266077Sdes } 1078266077Sdes return 1; 1079266077Sdes } 1080266077Sdes return sldns_str_print(s, sl, "\\%03u", (unsigned)c); 1081266077Sdes} 1082266077Sdes 1083266077Sdesint sldns_wire2str_str_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) 1084266077Sdes{ 1085266077Sdes int w = 0; 1086266077Sdes size_t i, len; 1087266077Sdes if(*dl < 1) return -1; 1088266077Sdes len = **d; 1089266077Sdes if(*dl < 1+len) return -1; 1090266077Sdes (*d)++; 1091266077Sdes (*dl)--; 1092266077Sdes w += sldns_str_print(s, sl, "\""); 1093266077Sdes for(i=0; i<len; i++) 1094266077Sdes w += str_char_print(s, sl, (*d)[i]); 1095266077Sdes w += sldns_str_print(s, sl, "\""); 1096266077Sdes (*d)+=len; 1097266077Sdes (*dl)-=len; 1098266077Sdes return w; 1099266077Sdes} 1100266077Sdes 1101266077Sdesint sldns_wire2str_apl_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) 1102266077Sdes{ 1103266077Sdes int i, w = 0; 1104266077Sdes uint16_t family; 1105266077Sdes uint8_t negation, prefix, adflength; 1106266077Sdes if(*dl < 4) return -1; 1107266077Sdes family = sldns_read_uint16(*d); 1108266077Sdes prefix = (*d)[2]; 1109266077Sdes negation = ((*d)[3] & LDNS_APL_NEGATION); 1110266077Sdes adflength = ((*d)[3] & LDNS_APL_MASK); 1111266077Sdes if(*dl < 4+(size_t)adflength) return -1; 1112266077Sdes if(family != LDNS_APL_IP4 && family != LDNS_APL_IP6) 1113266077Sdes return -1; /* unknown address family */ 1114266077Sdes if(negation) 1115266077Sdes w += sldns_str_print(s, sl, "!"); 1116266077Sdes w += sldns_str_print(s, sl, "%u:", (unsigned)family); 1117266077Sdes if(family == LDNS_APL_IP4) { 1118266077Sdes /* check if prefix <32 ? */ 1119266077Sdes /* address is variable length 0 - 4 */ 1120266077Sdes for(i=0; i<4; i++) { 1121266077Sdes if(i > 0) 1122266077Sdes w += sldns_str_print(s, sl, "."); 1123266077Sdes if(i < (int)adflength) 1124266077Sdes w += sldns_str_print(s, sl, "%d", (*d)[4+i]); 1125266077Sdes else w += sldns_str_print(s, sl, "0"); 1126266077Sdes } 1127266077Sdes } else if(family == LDNS_APL_IP6) { 1128266077Sdes /* check if prefix <128 ? */ 1129266077Sdes /* address is variable length 0 - 16 */ 1130266077Sdes for(i=0; i<16; i++) { 1131266077Sdes if(i%2 == 0 && i>0) 1132266077Sdes w += sldns_str_print(s, sl, ":"); 1133266077Sdes if(i < (int)adflength) 1134266077Sdes w += sldns_str_print(s, sl, "%02x", (*d)[4+i]); 1135266077Sdes else w += sldns_str_print(s, sl, "00"); 1136266077Sdes } 1137266077Sdes } 1138266077Sdes w += sldns_str_print(s, sl, "/%u", (unsigned)prefix); 1139266077Sdes (*d) += 4+adflength; 1140266077Sdes (*dl) -= 4+adflength; 1141266077Sdes return w; 1142266077Sdes} 1143266077Sdes 1144266077Sdesint sldns_wire2str_b32_ext_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) 1145266077Sdes{ 1146266077Sdes size_t datalen; 1147266077Sdes size_t sz; 1148266077Sdes if(*dl < 1) return -1; 1149266077Sdes datalen = (*d)[0]; 1150266077Sdes if(*dl < 1+datalen) return -1; 1151266077Sdes sz = sldns_b32_ntop_calculate_size(datalen); 1152266077Sdes if(*sl < sz+1) { 1153266077Sdes (*d) += datalen+1; 1154266077Sdes (*dl) -= (datalen+1); 1155266077Sdes return (int)sz; /* out of space really, but would need buffer 1156266077Sdes in order to truncate the output */ 1157266077Sdes } 1158266077Sdes sldns_b32_ntop_extended_hex((*d)+1, datalen, *s, *sl); 1159266077Sdes (*d) += datalen+1; 1160266077Sdes (*dl) -= (datalen+1); 1161266077Sdes (*s) += sz; 1162266077Sdes (*sl) -= sz; 1163266077Sdes return (int)sz; 1164266077Sdes} 1165266077Sdes 1166266077Sdes/** scan number of bytes from wire into b64 presentation format */ 1167266077Sdesstatic int sldns_wire2str_b64_scan_num(uint8_t** d, size_t* dl, char** s, 1168266077Sdes size_t* sl, size_t num) 1169266077Sdes{ 1170266077Sdes /* b64_ntop_calculate size includes null at the end */ 1171266077Sdes size_t sz = sldns_b64_ntop_calculate_size(num)-1; 1172266077Sdes if(*sl < sz+1) { 1173266077Sdes (*d) += num; 1174266077Sdes (*dl) -= num; 1175266077Sdes return (int)sz; /* out of space really, but would need buffer 1176266077Sdes in order to truncate the output */ 1177266077Sdes } 1178266077Sdes sldns_b64_ntop(*d, num, *s, *sl); 1179266077Sdes (*d) += num; 1180266077Sdes (*dl) -= num; 1181266077Sdes (*s) += sz; 1182266077Sdes (*sl) -= sz; 1183266077Sdes return (int)sz; 1184266077Sdes} 1185266077Sdes 1186266077Sdesint sldns_wire2str_b64_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) 1187266077Sdes{ 1188266077Sdes return sldns_wire2str_b64_scan_num(d, dl, s, sl, *dl); 1189266077Sdes} 1190266077Sdes 1191266077Sdesint sldns_wire2str_hex_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) 1192266077Sdes{ 1193266077Sdes return print_remainder_hex("", d, dl, s, sl); 1194266077Sdes} 1195266077Sdes 1196266077Sdesint sldns_wire2str_nsec_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) 1197266077Sdes{ 1198266077Sdes uint8_t* p = *d; 1199266077Sdes size_t pl = *dl; 1200266077Sdes unsigned i, bit, window, block_len; 1201266077Sdes uint16_t t; 1202266077Sdes int w = 0; 1203266077Sdes 1204266077Sdes /* check for errors */ 1205266077Sdes while(pl) { 1206266077Sdes if(pl < 2) return -1; 1207266077Sdes block_len = (unsigned)p[1]; 1208266077Sdes if(pl < 2+block_len) return -1; 1209266077Sdes p += block_len+2; 1210266077Sdes pl -= block_len+2; 1211266077Sdes } 1212266077Sdes 1213266077Sdes /* do it */ 1214266077Sdes p = *d; 1215266077Sdes pl = *dl; 1216266077Sdes while(pl) { 1217266077Sdes if(pl < 2) return -1; /* cannot happen */ 1218266077Sdes window = (unsigned)p[0]; 1219266077Sdes block_len = (unsigned)p[1]; 1220266077Sdes if(pl < 2+block_len) return -1; /* cannot happen */ 1221266077Sdes p += 2; 1222266077Sdes for(i=0; i<block_len; i++) { 1223266077Sdes if(p[i] == 0) continue; 1224266077Sdes /* base type number for this octet */ 1225266077Sdes t = ((window)<<8) | (i << 3); 1226266077Sdes for(bit=0; bit<8; bit++) { 1227266077Sdes if((p[i]&(0x80>>bit))) { 1228266077Sdes if(w) w += sldns_str_print(s, sl, " "); 1229266077Sdes w += sldns_wire2str_type_print(s, sl, 1230266077Sdes t+bit); 1231266077Sdes } 1232266077Sdes } 1233266077Sdes } 1234266077Sdes p += block_len; 1235266077Sdes pl -= block_len+2; 1236266077Sdes } 1237266077Sdes (*d) += *dl; 1238266077Sdes (*dl) = 0; 1239266077Sdes return w; 1240266077Sdes} 1241266077Sdes 1242266077Sdesint sldns_wire2str_nsec3_salt_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) 1243266077Sdes{ 1244266077Sdes size_t salt_len; 1245266077Sdes int w; 1246266077Sdes if(*dl < 1) return -1; 1247266077Sdes salt_len = (size_t)(*d)[0]; 1248266077Sdes if(*dl < 1+salt_len) return -1; 1249266077Sdes (*d)++; 1250266077Sdes (*dl)--; 1251266077Sdes if(salt_len == 0) { 1252266077Sdes return sldns_str_print(s, sl, "-"); 1253266077Sdes } 1254266077Sdes w = print_hex_buf(s, sl, *d, salt_len); 1255266077Sdes (*dl)-=salt_len; 1256266077Sdes (*d)+=salt_len; 1257266077Sdes return w; 1258266077Sdes} 1259266077Sdes 1260266077Sdesint sldns_wire2str_cert_alg_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) 1261266077Sdes{ 1262266077Sdes sldns_lookup_table *lt; 1263266077Sdes int data, w; 1264266077Sdes if(*dl < 2) return -1; 1265266077Sdes data = (int)sldns_read_uint16(*d); 1266266077Sdes lt = sldns_lookup_by_id(sldns_cert_algorithms, data); 1267266077Sdes if(lt && lt->name) 1268266077Sdes w = sldns_str_print(s, sl, "%s", lt->name); 1269266077Sdes else w = sldns_str_print(s, sl, "%d", data); 1270266077Sdes (*dl)-=2; 1271266077Sdes (*d)+=2; 1272266077Sdes return w; 1273266077Sdes} 1274266077Sdes 1275266077Sdesint sldns_wire2str_alg_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) 1276266077Sdes{ 1277266077Sdes /* don't use algorithm mnemonics in the presentation format 1278266077Sdes * this kind of got sneaked into the rfc's */ 1279266077Sdes return sldns_wire2str_int8_scan(d, dl, s, sl); 1280266077Sdes} 1281266077Sdes 1282266077Sdesint sldns_wire2str_unknown_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) 1283266077Sdes{ 1284266077Sdes return sldns_wire2str_rdata_unknown_scan(d, dl, s, sl); 1285266077Sdes} 1286266077Sdes 1287266077Sdesint sldns_wire2str_time_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) 1288266077Sdes{ 1289266077Sdes /* create a YYYYMMDDHHMMSS string if possible */ 1290266077Sdes struct tm tm; 1291266077Sdes char date_buf[16]; 1292266077Sdes uint32_t t; 1293266077Sdes memset(&tm, 0, sizeof(tm)); 1294266077Sdes if(*dl < 4) return -1; 1295266077Sdes t = sldns_read_uint32(*d); 1296266077Sdes date_buf[15]=0; 1297266077Sdes if(sldns_serial_arithmitics_gmtime_r(t, time(NULL), &tm) && 1298266077Sdes strftime(date_buf, 15, "%Y%m%d%H%M%S", &tm)) { 1299266077Sdes (*d) += 4; 1300266077Sdes (*dl) -= 4; 1301266077Sdes return sldns_str_print(s, sl, "%s", date_buf); 1302266077Sdes } 1303266077Sdes return -1; 1304266077Sdes} 1305266077Sdes 1306266077Sdesstatic int 1307266077Sdesloc_cm_print(char** str, size_t* sl, uint8_t mantissa, uint8_t exponent) 1308266077Sdes{ 1309266077Sdes int w = 0; 1310266077Sdes uint8_t i; 1311266077Sdes /* is it 0.<two digits> ? */ 1312266077Sdes if(exponent < 2) { 1313266077Sdes if(exponent == 1) 1314266077Sdes mantissa *= 10; 1315266077Sdes return sldns_str_print(str, sl, "0.%02ld", (long)mantissa); 1316266077Sdes } 1317266077Sdes /* always <digit><string of zeros> */ 1318266077Sdes w += sldns_str_print(str, sl, "%d", (int)mantissa); 1319266077Sdes for(i=0; i<exponent-2; i++) 1320266077Sdes w += sldns_str_print(str, sl, "0"); 1321266077Sdes return w; 1322266077Sdes} 1323266077Sdes 1324266077Sdesint sldns_wire2str_loc_scan(uint8_t** d, size_t* dl, char** str, size_t* sl) 1325266077Sdes{ 1326266077Sdes /* we could do checking (ie degrees < 90 etc)? */ 1327266077Sdes uint8_t version; 1328266077Sdes uint8_t size; 1329266077Sdes uint8_t horizontal_precision; 1330266077Sdes uint8_t vertical_precision; 1331266077Sdes uint32_t longitude; 1332266077Sdes uint32_t latitude; 1333266077Sdes uint32_t altitude; 1334266077Sdes char northerness; 1335266077Sdes char easterness; 1336266077Sdes uint32_t h; 1337266077Sdes uint32_t m; 1338266077Sdes double s; 1339266077Sdes uint32_t equator = (uint32_t)1 << 31; /* 2**31 */ 1340266077Sdes int w = 0; 1341266077Sdes 1342266077Sdes if(*dl < 16) return -1; 1343266077Sdes version = (*d)[0]; 1344266077Sdes if(version != 0) 1345266077Sdes return sldns_wire2str_hex_scan(d, dl, str, sl); 1346266077Sdes size = (*d)[1]; 1347266077Sdes horizontal_precision = (*d)[2]; 1348266077Sdes vertical_precision = (*d)[3]; 1349266077Sdes 1350266077Sdes latitude = sldns_read_uint32((*d)+4); 1351266077Sdes longitude = sldns_read_uint32((*d)+8); 1352266077Sdes altitude = sldns_read_uint32((*d)+12); 1353266077Sdes 1354266077Sdes if (latitude > equator) { 1355266077Sdes northerness = 'N'; 1356266077Sdes latitude = latitude - equator; 1357266077Sdes } else { 1358266077Sdes northerness = 'S'; 1359266077Sdes latitude = equator - latitude; 1360266077Sdes } 1361266077Sdes h = latitude / (1000 * 60 * 60); 1362266077Sdes latitude = latitude % (1000 * 60 * 60); 1363266077Sdes m = latitude / (1000 * 60); 1364266077Sdes latitude = latitude % (1000 * 60); 1365266077Sdes s = (double) latitude / 1000.0; 1366266077Sdes w += sldns_str_print(str, sl, "%02u %02u %06.3f %c ", 1367266077Sdes h, m, s, northerness); 1368266077Sdes 1369266077Sdes if (longitude > equator) { 1370266077Sdes easterness = 'E'; 1371266077Sdes longitude = longitude - equator; 1372266077Sdes } else { 1373266077Sdes easterness = 'W'; 1374266077Sdes longitude = equator - longitude; 1375266077Sdes } 1376266077Sdes h = longitude / (1000 * 60 * 60); 1377266077Sdes longitude = longitude % (1000 * 60 * 60); 1378266077Sdes m = longitude / (1000 * 60); 1379266077Sdes longitude = longitude % (1000 * 60); 1380266077Sdes s = (double) longitude / (1000.0); 1381266077Sdes w += sldns_str_print(str, sl, "%02u %02u %06.3f %c ", 1382266077Sdes h, m, s, easterness); 1383266077Sdes 1384266077Sdes s = ((double) altitude) / 100; 1385266077Sdes s -= 100000; 1386266077Sdes 1387266077Sdes if(altitude%100 != 0) 1388266077Sdes w += sldns_str_print(str, sl, "%.2f", s); 1389266077Sdes else 1390266077Sdes w += sldns_str_print(str, sl, "%.0f", s); 1391266077Sdes 1392266077Sdes w += sldns_str_print(str, sl, "m "); 1393266077Sdes 1394266077Sdes w += loc_cm_print(str, sl, (size & 0xf0) >> 4, size & 0x0f); 1395266077Sdes w += sldns_str_print(str, sl, "m "); 1396266077Sdes 1397266077Sdes w += loc_cm_print(str, sl, (horizontal_precision & 0xf0) >> 4, 1398266077Sdes horizontal_precision & 0x0f); 1399266077Sdes w += sldns_str_print(str, sl, "m "); 1400266077Sdes 1401266077Sdes w += loc_cm_print(str, sl, (vertical_precision & 0xf0) >> 4, 1402266077Sdes vertical_precision & 0x0f); 1403266077Sdes w += sldns_str_print(str, sl, "m"); 1404266077Sdes 1405266077Sdes (*d)+=16; 1406266077Sdes (*dl)-=16; 1407266077Sdes return w; 1408266077Sdes} 1409266077Sdes 1410266077Sdesint sldns_wire2str_wks_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) 1411266077Sdes{ 1412266077Sdes /* protocol, followed by bitmap of services */ 1413266077Sdes const char* proto_name = NULL; 1414266077Sdes struct protoent *protocol; 1415266077Sdes struct servent *service; 1416266077Sdes uint8_t protocol_nr; 1417266077Sdes int bit, port, w = 0; 1418266077Sdes size_t i; 1419266077Sdes /* we cannot print with strings because they 1420266077Sdes * are not portable, the presentation format may 1421266077Sdes * not be able to be read in on another computer. */ 1422266077Sdes int print_symbols = 0; 1423266077Sdes 1424266077Sdes /* protocol */ 1425266077Sdes if(*dl < 1) return -1; 1426266077Sdes protocol_nr = (*d)[0]; 1427266077Sdes (*d)++; 1428266077Sdes (*dl)--; 1429266077Sdes protocol = getprotobynumber((int)protocol_nr); 1430266077Sdes if(protocol && (protocol->p_name != NULL)) { 1431266077Sdes w += sldns_str_print(s, sl, "%s", protocol->p_name); 1432266077Sdes proto_name = protocol->p_name; 1433266077Sdes } else { 1434266077Sdes w += sldns_str_print(s, sl, "%u", (unsigned)protocol_nr); 1435266077Sdes } 1436266077Sdes 1437266077Sdes for(i=0; i<*dl; i++) { 1438266077Sdes if((*d)[i] == 0) 1439266077Sdes continue; 1440266077Sdes for(bit=0; bit<8; bit++) { 1441266077Sdes if(!(((*d)[i])&(0x80>>bit))) 1442266077Sdes continue; 1443266077Sdes port = (int)i*8 + bit; 1444266077Sdes 1445266077Sdes if(!print_symbols) 1446266077Sdes service = NULL; 1447266077Sdes else 1448266077Sdes service = getservbyport( 1449266077Sdes (int)htons((uint16_t)port), proto_name); 1450266077Sdes if(service && service->s_name) 1451266077Sdes w += sldns_str_print(s, sl, " %s", 1452266077Sdes service->s_name); 1453266077Sdes else w += sldns_str_print(s, sl, " %u", 1454266077Sdes (unsigned)port); 1455266077Sdes } 1456266077Sdes } 1457266077Sdes 1458266077Sdes#ifdef HAVE_ENDSERVENT 1459266077Sdes endservent(); 1460266077Sdes#endif 1461266077Sdes#ifdef HAVE_ENDPROTOENT 1462266077Sdes endprotoent(); 1463266077Sdes#endif 1464266077Sdes (*d) += *dl; 1465266077Sdes (*dl) = 0; 1466266077Sdes return w; 1467266077Sdes} 1468266077Sdes 1469266077Sdesint sldns_wire2str_nsap_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) 1470266077Sdes{ 1471266077Sdes return print_remainder_hex("0x", d, dl, s, sl); 1472266077Sdes} 1473266077Sdes 1474266077Sdesint sldns_wire2str_atma_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) 1475266077Sdes{ 1476266077Sdes return print_remainder_hex("", d, dl, s, sl); 1477266077Sdes} 1478266077Sdes 1479266077Sdes/* internal scan routine that can modify arguments on failure */ 1480266077Sdesstatic int sldns_wire2str_ipseckey_scan_internal(uint8_t** d, size_t* dl, 1481266077Sdes char** s, size_t* sl, uint8_t* pkt, size_t pktlen) 1482266077Sdes{ 1483266077Sdes /* http://www.ietf.org/internet-drafts/draft-ietf-ipseckey-rr-12.txt*/ 1484266077Sdes uint8_t precedence, gateway_type, algorithm; 1485266077Sdes int w = 0; 1486266077Sdes 1487266077Sdes if(*dl < 3) return -1; 1488266077Sdes precedence = (*d)[0]; 1489266077Sdes gateway_type = (*d)[1]; 1490266077Sdes algorithm = (*d)[2]; 1491266077Sdes if(gateway_type > 3) 1492266077Sdes return -1; /* unknown */ 1493266077Sdes (*d)+=3; 1494266077Sdes (*dl)-=3; 1495266077Sdes w += sldns_str_print(s, sl, "%d %d %d ", 1496266077Sdes (int)precedence, (int)gateway_type, (int)algorithm); 1497266077Sdes 1498266077Sdes switch(gateway_type) { 1499266077Sdes case 0: /* no gateway */ 1500266077Sdes w += sldns_str_print(s, sl, "."); 1501266077Sdes break; 1502266077Sdes case 1: /* ip4 */ 1503266077Sdes w += sldns_wire2str_a_scan(d, dl, s, sl); 1504266077Sdes break; 1505266077Sdes case 2: /* ip6 */ 1506266077Sdes w += sldns_wire2str_aaaa_scan(d, dl, s, sl); 1507266077Sdes break; 1508266077Sdes case 3: /* dname */ 1509266077Sdes w += sldns_wire2str_dname_scan(d, dl, s, sl, pkt, pktlen); 1510266077Sdes break; 1511266077Sdes default: /* unknown */ 1512266077Sdes return -1; 1513266077Sdes } 1514266077Sdes 1515266077Sdes if(*dl < 1) 1516266077Sdes return -1; 1517266077Sdes w += sldns_str_print(s, sl, " "); 1518266077Sdes w += sldns_wire2str_b64_scan_num(d, dl, s, sl, *dl); 1519266077Sdes return w; 1520266077Sdes} 1521266077Sdes 1522266077Sdesint sldns_wire2str_ipseckey_scan(uint8_t** d, size_t* dl, char** s, size_t* sl, 1523266077Sdes uint8_t* pkt, size_t pktlen) 1524266077Sdes{ 1525266077Sdes uint8_t* od = *d; 1526266077Sdes char* os = *s; 1527266077Sdes size_t odl = *dl, osl = *sl; 1528266077Sdes int w=sldns_wire2str_ipseckey_scan_internal(d, dl, s, sl, pkt, pktlen); 1529266077Sdes if(w == -1) { 1530266077Sdes *d = od; 1531266077Sdes *s = os; 1532266077Sdes *dl = odl; 1533266077Sdes *sl = osl; 1534266077Sdes return -1; 1535266077Sdes } 1536266077Sdes return w; 1537266077Sdes} 1538266077Sdes 1539266077Sdesint sldns_wire2str_hip_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) 1540266077Sdes{ 1541266077Sdes int w; 1542266077Sdes uint8_t algo, hitlen; 1543266077Sdes uint16_t pklen; 1544266077Sdes 1545266077Sdes /* read lengths */ 1546266077Sdes if(*dl < 4) 1547266077Sdes return -1; 1548266077Sdes hitlen = (*d)[0]; 1549266077Sdes algo = (*d)[1]; 1550266077Sdes pklen = sldns_read_uint16((*d)+2); 1551266077Sdes if(*dl < (size_t)4 + (size_t)hitlen + (size_t)pklen) 1552266077Sdes return -1; 1553266077Sdes 1554266077Sdes /* write: algo hit pubkey */ 1555266077Sdes w = sldns_str_print(s, sl, "%u ", (unsigned)algo); 1556266077Sdes w += print_hex_buf(s, sl, (*d)+4, hitlen); 1557266077Sdes w += sldns_str_print(s, sl, " "); 1558266077Sdes (*d)+=4+hitlen; 1559266077Sdes (*dl)-= (4+hitlen); 1560266077Sdes w += sldns_wire2str_b64_scan_num(d, dl, s, sl, pklen); 1561266077Sdes return w; 1562266077Sdes} 1563266077Sdes 1564266077Sdesint sldns_wire2str_int16_data_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) 1565266077Sdes{ 1566266077Sdes uint16_t n; 1567266077Sdes if(*dl < 2) 1568266077Sdes return -1; 1569266077Sdes n = sldns_read_uint16(*d); 1570266077Sdes if(*dl < 2+(size_t)n) 1571266077Sdes return -1; 1572266077Sdes (*d)+=2; 1573266077Sdes (*dl)-=2; 1574266077Sdes return sldns_wire2str_b64_scan_num(d, dl, s, sl, n); 1575266077Sdes} 1576266077Sdes 1577266077Sdesint sldns_wire2str_nsec3_next_owner_scan(uint8_t** d, size_t* dl, char** s, 1578266077Sdes size_t* sl) 1579266077Sdes{ 1580266077Sdes return sldns_wire2str_b32_ext_scan(d, dl, s, sl); 1581266077Sdes} 1582266077Sdes 1583266077Sdesint sldns_wire2str_ilnp64_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) 1584266077Sdes{ 1585266077Sdes int w; 1586266077Sdes if(*dl < 8) 1587266077Sdes return -1; 1588266077Sdes w = sldns_str_print(s, sl, "%.4x:%.4x:%.4x:%.4x", 1589266077Sdes sldns_read_uint16(*d), sldns_read_uint16((*d)+2), 1590266077Sdes sldns_read_uint16((*d)+4), sldns_read_uint16((*d)+6)); 1591266077Sdes (*d)+=8; 1592266077Sdes (*dl)-=8; 1593266077Sdes return w; 1594266077Sdes} 1595266077Sdes 1596266077Sdesint sldns_wire2str_eui48_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) 1597266077Sdes{ 1598266077Sdes int w; 1599266077Sdes if(*dl < 6) 1600266077Sdes return -1; 1601266077Sdes w = sldns_str_print(s, sl, "%.2x-%.2x-%.2x-%.2x-%.2x-%.2x", 1602266077Sdes (*d)[0], (*d)[1], (*d)[2], (*d)[3], (*d)[4], (*d)[5]); 1603266077Sdes (*d)+=6; 1604266077Sdes (*dl)-=6; 1605266077Sdes return w; 1606266077Sdes} 1607266077Sdes 1608266077Sdesint sldns_wire2str_eui64_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) 1609266077Sdes{ 1610266077Sdes int w; 1611266077Sdes if(*dl < 8) 1612266077Sdes return -1; 1613266077Sdes w = sldns_str_print(s, sl, "%.2x-%.2x-%.2x-%.2x-%.2x-%.2x-%.2x-%.2x", 1614266077Sdes (*d)[0], (*d)[1], (*d)[2], (*d)[3], (*d)[4], (*d)[5], 1615266077Sdes (*d)[6], (*d)[7]); 1616266077Sdes (*d)+=8; 1617266077Sdes (*dl)-=8; 1618266077Sdes return w; 1619266077Sdes} 1620266077Sdes 1621266077Sdesint sldns_wire2str_tag_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) 1622266077Sdes{ 1623266077Sdes size_t i, n; 1624266077Sdes int w = 0; 1625266077Sdes if(*dl < 1) 1626266077Sdes return -1; 1627266077Sdes n = (size_t)((*d)[0]); 1628266077Sdes if(*dl < 1+n) 1629266077Sdes return -1; 1630266077Sdes for(i=0; i<n; i++) 1631276541Sdes if(!isalnum((unsigned char)(*d)[i])) 1632266077Sdes return -1; 1633266077Sdes for(i=0; i<n; i++) 1634266077Sdes w += sldns_str_print(s, sl, "%c", (char)(*d)[i]); 1635266077Sdes (*d)+=n+1; 1636266077Sdes (*dl)-=(n+1); 1637266077Sdes return w; 1638266077Sdes} 1639266077Sdes 1640266077Sdesint sldns_wire2str_long_str_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) 1641266077Sdes{ 1642266077Sdes size_t i; 1643266077Sdes int w = 0; 1644266077Sdes w += sldns_str_print(s, sl, "\""); 1645266077Sdes for(i=0; i<*dl; i++) 1646266077Sdes w += str_char_print(s, sl, (*d)[i]); 1647266077Sdes w += sldns_str_print(s, sl, "\""); 1648266077Sdes (*d)+=*dl; 1649266077Sdes (*dl)=0; 1650266077Sdes return w; 1651266077Sdes} 1652266077Sdes 1653266077Sdesint sldns_wire2str_edns_llq_print(char** s, size_t* sl, uint8_t* data, 1654266077Sdes size_t len) 1655266077Sdes{ 1656266077Sdes /* LLQ constants */ 1657266077Sdes const char* llq_errors[] = {"NO-ERROR", "SERV-FULL", "STATIC", 1658266077Sdes "FORMAT-ERR", "NO-SUCH-LLQ", "BAD-VERS", "UNKNOWN_ERR"}; 1659266077Sdes const unsigned int llq_errors_num = 7; 1660266077Sdes const char* llq_opcodes[] = {"LLQ-SETUP", "LLQ-REFRESH", "LLQ-EVENT"}; 1661266077Sdes const unsigned int llq_opcodes_num = 3; 1662266077Sdes uint16_t version, llq_opcode, error_code; 1663266077Sdes uint64_t llq_id; 1664266077Sdes uint32_t lease_life; /* Requested or granted life of LLQ, in seconds */ 1665266077Sdes int w = 0; 1666266077Sdes 1667266077Sdes /* read the record */ 1668266077Sdes if(len != 18) { 1669266077Sdes w += sldns_str_print(s, sl, "malformed LLQ "); 1670266077Sdes w += print_hex_buf(s, sl, data, len); 1671266077Sdes return w; 1672266077Sdes } 1673266077Sdes version = sldns_read_uint16(data); 1674266077Sdes llq_opcode = sldns_read_uint16(data+2); 1675266077Sdes error_code = sldns_read_uint16(data+4); 1676266077Sdes memmove(&llq_id, data+6, sizeof(llq_id)); 1677266077Sdes lease_life = sldns_read_uint32(data+14); 1678266077Sdes 1679266077Sdes /* print it */ 1680266077Sdes w += sldns_str_print(s, sl, "v%d ", (int)version); 1681266077Sdes if(llq_opcode < llq_opcodes_num) 1682266077Sdes w += sldns_str_print(s, sl, "%s", llq_opcodes[llq_opcode]); 1683266077Sdes else w += sldns_str_print(s, sl, "opcode %d", (int)llq_opcode); 1684266077Sdes if(error_code < llq_errors_num) 1685266077Sdes w += sldns_str_print(s, sl, " %s", llq_errors[error_code]); 1686266077Sdes else w += sldns_str_print(s, sl, " error %d", (int)error_code); 1687266077Sdes#ifndef USE_WINSOCK 1688266077Sdes w += sldns_str_print(s, sl, " id %llx lease-life %lu", 1689266077Sdes (unsigned long long)llq_id, (unsigned long)lease_life); 1690266077Sdes#else 1691266077Sdes w += sldns_str_print(s, sl, " id %I64x lease-life %lu", 1692266077Sdes (unsigned long long)llq_id, (unsigned long)lease_life); 1693266077Sdes#endif 1694266077Sdes return w; 1695266077Sdes} 1696266077Sdes 1697266077Sdesint sldns_wire2str_edns_ul_print(char** s, size_t* sl, uint8_t* data, 1698266077Sdes size_t len) 1699266077Sdes{ 1700266077Sdes uint32_t lease; 1701266077Sdes int w = 0; 1702266077Sdes if(len != 4) { 1703266077Sdes w += sldns_str_print(s, sl, "malformed UL "); 1704266077Sdes w += print_hex_buf(s, sl, data, len); 1705266077Sdes return w; 1706266077Sdes } 1707266077Sdes lease = sldns_read_uint32(data); 1708266077Sdes w += sldns_str_print(s, sl, "lease %lu", (unsigned long)lease); 1709266077Sdes return w; 1710266077Sdes} 1711266077Sdes 1712266077Sdesint sldns_wire2str_edns_nsid_print(char** s, size_t* sl, uint8_t* data, 1713266077Sdes size_t len) 1714266077Sdes{ 1715266077Sdes int w = 0; 1716266077Sdes size_t i, printed=0; 1717266077Sdes w += print_hex_buf(s, sl, data, len); 1718266077Sdes for(i=0; i<len; i++) { 1719276541Sdes if(isprint((unsigned char)data[i]) || data[i] == '\t') { 1720266077Sdes if(!printed) { 1721266077Sdes w += sldns_str_print(s, sl, " ("); 1722266077Sdes printed = 1; 1723266077Sdes } 1724266077Sdes w += sldns_str_print(s, sl, "%c", (char)data[i]); 1725266077Sdes } 1726266077Sdes } 1727266077Sdes if(printed) 1728266077Sdes w += sldns_str_print(s, sl, ")"); 1729266077Sdes return w; 1730266077Sdes} 1731266077Sdes 1732266077Sdesint sldns_wire2str_edns_dau_print(char** s, size_t* sl, uint8_t* data, 1733266077Sdes size_t len) 1734266077Sdes{ 1735266077Sdes sldns_lookup_table *lt; 1736266077Sdes size_t i; 1737266077Sdes int w = 0; 1738266077Sdes for(i=0; i<len; i++) { 1739266077Sdes lt = sldns_lookup_by_id(sldns_algorithms, (int)data[i]); 1740266077Sdes if(lt && lt->name) 1741266077Sdes w += sldns_str_print(s, sl, " %s", lt->name); 1742266077Sdes else w += sldns_str_print(s, sl, " %d", (int)data[i]); 1743266077Sdes } 1744266077Sdes return w; 1745266077Sdes} 1746266077Sdes 1747266077Sdesint sldns_wire2str_edns_dhu_print(char** s, size_t* sl, uint8_t* data, 1748266077Sdes size_t len) 1749266077Sdes{ 1750266077Sdes sldns_lookup_table *lt; 1751266077Sdes size_t i; 1752266077Sdes int w = 0; 1753266077Sdes for(i=0; i<len; i++) { 1754266077Sdes lt = sldns_lookup_by_id(sldns_hashes, (int)data[i]); 1755266077Sdes if(lt && lt->name) 1756266077Sdes w += sldns_str_print(s, sl, " %s", lt->name); 1757266077Sdes else w += sldns_str_print(s, sl, " %d", (int)data[i]); 1758266077Sdes } 1759266077Sdes return w; 1760266077Sdes} 1761266077Sdes 1762266077Sdesint sldns_wire2str_edns_n3u_print(char** s, size_t* sl, uint8_t* data, 1763266077Sdes size_t len) 1764266077Sdes{ 1765266077Sdes size_t i; 1766266077Sdes int w = 0; 1767266077Sdes for(i=0; i<len; i++) { 1768266077Sdes if(data[i] == 1) 1769266077Sdes w += sldns_str_print(s, sl, " SHA1"); 1770266077Sdes else w += sldns_str_print(s, sl, " %d", (int)data[i]); 1771266077Sdes } 1772266077Sdes return w; 1773266077Sdes} 1774266077Sdes 1775266077Sdesint sldns_wire2str_edns_subnet_print(char** s, size_t* sl, uint8_t* data, 1776266077Sdes size_t len) 1777266077Sdes{ 1778266077Sdes int w = 0; 1779266077Sdes uint16_t family; 1780266077Sdes uint8_t source, scope; 1781266077Sdes if(len < 4) { 1782266077Sdes w += sldns_str_print(s, sl, "malformed subnet "); 1783266077Sdes w += print_hex_buf(s, sl, data, len); 1784266077Sdes return w; 1785266077Sdes } 1786266077Sdes family = sldns_read_uint16(data); 1787266077Sdes source = data[2]; 1788266077Sdes scope = data[3]; 1789266077Sdes if(family == 1) { 1790266077Sdes /* IP4 */ 1791266077Sdes char buf[64]; 1792266077Sdes uint8_t ip4[4]; 1793266077Sdes memset(ip4, 0, sizeof(ip4)); 1794266077Sdes if(len-4 > 4) { 1795266077Sdes w += sldns_str_print(s, sl, "trailingdata:"); 1796266077Sdes w += print_hex_buf(s, sl, data+4+4, len-4-4); 1797266077Sdes w += sldns_str_print(s, sl, " "); 1798266077Sdes len = 4+4; 1799266077Sdes } 1800266077Sdes memmove(ip4, data+4, len-4); 1801266077Sdes if(!inet_ntop(AF_INET, ip4, buf, (socklen_t)sizeof(buf))) { 1802266077Sdes w += sldns_str_print(s, sl, "ip4ntoperror "); 1803266077Sdes w += print_hex_buf(s, sl, data+4+4, len-4-4); 1804266077Sdes } else { 1805266077Sdes w += sldns_str_print(s, sl, "%s", buf); 1806266077Sdes } 1807266077Sdes } else if(family == 2) { 1808266077Sdes /* IP6 */ 1809266077Sdes char buf[64]; 1810266077Sdes uint8_t ip6[16]; 1811266077Sdes memset(ip6, 0, sizeof(ip6)); 1812266077Sdes if(len-4 > 16) { 1813266077Sdes w += sldns_str_print(s, sl, "trailingdata:"); 1814266077Sdes w += print_hex_buf(s, sl, data+4+16, len-4-16); 1815266077Sdes w += sldns_str_print(s, sl, " "); 1816266077Sdes len = 4+16; 1817266077Sdes } 1818266077Sdes memmove(ip6, data+4, len-4); 1819266077Sdes#ifdef AF_INET6 1820266077Sdes if(!inet_ntop(AF_INET6, ip6, buf, (socklen_t)sizeof(buf))) { 1821266077Sdes w += sldns_str_print(s, sl, "ip6ntoperror "); 1822266077Sdes w += print_hex_buf(s, sl, data+4+4, len-4-4); 1823266077Sdes } else { 1824266077Sdes w += sldns_str_print(s, sl, "%s", buf); 1825266077Sdes } 1826266077Sdes#else 1827266077Sdes w += print_hex_buf(s, sl, data+4+4, len-4-4); 1828266077Sdes#endif 1829266077Sdes } else { 1830266077Sdes /* unknown */ 1831266077Sdes w += sldns_str_print(s, sl, "family %d ", 1832266077Sdes (int)family); 1833266077Sdes w += print_hex_buf(s, sl, data, len); 1834266077Sdes } 1835266077Sdes w += sldns_str_print(s, sl, "/%d scope /%d", (int)source, (int)scope); 1836266077Sdes return w; 1837266077Sdes} 1838266077Sdes 1839266077Sdesint sldns_wire2str_edns_option_print(char** s, size_t* sl, 1840266077Sdes uint16_t option_code, uint8_t* optdata, size_t optlen) 1841266077Sdes{ 1842266077Sdes int w = 0; 1843266077Sdes w += sldns_wire2str_edns_option_code_print(s, sl, option_code); 1844266077Sdes w += sldns_str_print(s, sl, ": "); 1845266077Sdes switch(option_code) { 1846266077Sdes case LDNS_EDNS_LLQ: 1847266077Sdes w += sldns_wire2str_edns_llq_print(s, sl, optdata, optlen); 1848266077Sdes break; 1849266077Sdes case LDNS_EDNS_UL: 1850266077Sdes w += sldns_wire2str_edns_ul_print(s, sl, optdata, optlen); 1851266077Sdes break; 1852266077Sdes case LDNS_EDNS_NSID: 1853266077Sdes w += sldns_wire2str_edns_nsid_print(s, sl, optdata, optlen); 1854266077Sdes break; 1855266077Sdes case LDNS_EDNS_DAU: 1856266077Sdes w += sldns_wire2str_edns_dau_print(s, sl, optdata, optlen); 1857266077Sdes break; 1858266077Sdes case LDNS_EDNS_DHU: 1859266077Sdes w += sldns_wire2str_edns_dhu_print(s, sl, optdata, optlen); 1860266077Sdes break; 1861266077Sdes case LDNS_EDNS_N3U: 1862266077Sdes w += sldns_wire2str_edns_n3u_print(s, sl, optdata, optlen); 1863266077Sdes break; 1864266077Sdes case LDNS_EDNS_CLIENT_SUBNET: 1865266077Sdes w += sldns_wire2str_edns_subnet_print(s, sl, optdata, optlen); 1866266077Sdes break; 1867266077Sdes default: 1868266077Sdes /* unknown option code */ 1869266077Sdes w += print_hex_buf(s, sl, optdata, optlen); 1870266077Sdes break; 1871266077Sdes } 1872266077Sdes return w; 1873266077Sdes} 1874266077Sdes 1875266077Sdes/** print the edns options to string */ 1876266077Sdesstatic int 1877266077Sdesprint_edns_opts(char** s, size_t* sl, uint8_t* rdata, size_t rdatalen) 1878266077Sdes{ 1879266077Sdes uint16_t option_code, option_len; 1880266077Sdes int w = 0; 1881266077Sdes while(rdatalen > 0) { 1882266077Sdes /* option name */ 1883266077Sdes if(rdatalen < 4) { 1884266077Sdes w += sldns_str_print(s, sl, " ; malformed: "); 1885266077Sdes w += print_hex_buf(s, sl, rdata, rdatalen); 1886266077Sdes return w; 1887266077Sdes } 1888266077Sdes option_code = sldns_read_uint16(rdata); 1889266077Sdes option_len = sldns_read_uint16(rdata+2); 1890266077Sdes rdata += 4; 1891266077Sdes rdatalen -= 4; 1892266077Sdes 1893266077Sdes /* option value */ 1894266077Sdes if(rdatalen < (size_t)option_len) { 1895266077Sdes w += sldns_str_print(s, sl, " ; malformed "); 1896266077Sdes w += sldns_wire2str_edns_option_code_print(s, sl, 1897266077Sdes option_code); 1898266077Sdes w += sldns_str_print(s, sl, ": "); 1899266077Sdes w += print_hex_buf(s, sl, rdata, rdatalen); 1900266077Sdes return w; 1901266077Sdes } 1902266077Sdes w += sldns_str_print(s, sl, " ; "); 1903266077Sdes w += sldns_wire2str_edns_option_print(s, sl, option_code, 1904266077Sdes rdata, option_len); 1905266077Sdes rdata += option_len; 1906266077Sdes rdatalen -= option_len; 1907266077Sdes } 1908266077Sdes return w; 1909266077Sdes} 1910266077Sdes 1911266077Sdesint sldns_wire2str_edns_scan(uint8_t** data, size_t* data_len, char** str, 1912266077Sdes size_t* str_len, uint8_t* pkt, size_t pktlen) 1913266077Sdes{ 1914266077Sdes int w = 0; 1915266077Sdes uint8_t ext_rcode, edns_version; 1916266077Sdes uint16_t udpsize, edns_bits, rdatalen; 1917266077Sdes w += sldns_str_print(str, str_len, "; EDNS:"); 1918266077Sdes 1919266077Sdes /* some input checks, domain name */ 1920266077Sdes if(*data_len < 1+10) 1921266077Sdes return w + print_remainder_hex("Error malformed 0x", 1922266077Sdes data, data_len, str, str_len); 1923266077Sdes if(*data[0] != 0) { 1924266077Sdes return w + print_remainder_hex("Error nonrootdname 0x", 1925266077Sdes data, data_len, str, str_len); 1926266077Sdes } 1927266077Sdes (*data)++; 1928266077Sdes (*data_len)--; 1929266077Sdes 1930266077Sdes /* check type and read fixed contents */ 1931266077Sdes if(sldns_read_uint16((*data)) != LDNS_RR_TYPE_OPT) { 1932266077Sdes return w + print_remainder_hex("Error nottypeOPT 0x", 1933266077Sdes data, data_len, str, str_len); 1934266077Sdes } 1935266077Sdes udpsize = sldns_read_uint16((*data)+2); 1936266077Sdes ext_rcode = (*data)[4]; 1937266077Sdes edns_version = (*data)[5]; 1938266077Sdes edns_bits = sldns_read_uint16((*data)+6); 1939266077Sdes rdatalen = sldns_read_uint16((*data)+8); 1940266077Sdes (*data)+=10; 1941266077Sdes (*data_len)-=10; 1942266077Sdes 1943266077Sdes w += sldns_str_print(str, str_len, " version: %u;", 1944266077Sdes (unsigned)edns_version); 1945266077Sdes w += sldns_str_print(str, str_len, " flags:"); 1946266077Sdes if((edns_bits & LDNS_EDNS_MASK_DO_BIT)) 1947266077Sdes w += sldns_str_print(str, str_len, " do"); 1948266077Sdes /* the extended rcode is the value set, shifted four bits, 1949266077Sdes * and or'd with the original rcode */ 1950266077Sdes if(ext_rcode) { 1951266077Sdes int rc = ((int)ext_rcode)<<4; 1952266077Sdes if(pkt && pktlen >= LDNS_HEADER_SIZE) 1953266077Sdes rc |= LDNS_RCODE_WIRE(pkt); 1954266077Sdes w += sldns_str_print(str, str_len, " ; ext-rcode: %d", rc); 1955266077Sdes } 1956266077Sdes w += sldns_str_print(str, str_len, " ; udp: %u", (unsigned)udpsize); 1957266077Sdes 1958266077Sdes if(rdatalen) { 1959266077Sdes if(*data_len < rdatalen) { 1960266077Sdes w += sldns_str_print(str, str_len, 1961266077Sdes " ; Error EDNS rdata too short; "); 1962266077Sdes rdatalen = *data_len; 1963266077Sdes } 1964266077Sdes w += print_edns_opts(str, str_len, *data, rdatalen); 1965266077Sdes (*data) += rdatalen; 1966266077Sdes (*data_len) -= rdatalen; 1967266077Sdes } 1968266077Sdes w += sldns_str_print(str, str_len, "\n"); 1969266077Sdes return w; 1970266077Sdes} 1971