diff options
Diffstat (limited to 'sldns/wire2str.c')
| -rw-r--r-- | sldns/wire2str.c | 73 |
1 files changed, 43 insertions, 30 deletions
diff --git a/sldns/wire2str.c b/sldns/wire2str.c index 01ec84b3c506..d0d1632d407d 100644 --- a/sldns/wire2str.c +++ b/sldns/wire2str.c @@ -22,6 +22,7 @@ #include "sldns/parseutil.h" #include "sldns/sbuffer.h" #include "sldns/keyraw.h" +#include "util/data/dname.h" #ifdef HAVE_TIME_H #include <time.h> #endif @@ -252,13 +253,13 @@ int sldns_wire2str_pkt_buf(uint8_t* d, size_t dlen, char* s, size_t slen) int sldns_wire2str_rr_buf(uint8_t* d, size_t dlen, char* s, size_t slen) { /* use arguments as temporary variables */ - return sldns_wire2str_rr_scan(&d, &dlen, &s, &slen, NULL, 0); + return sldns_wire2str_rr_scan(&d, &dlen, &s, &slen, NULL, 0, NULL); } int sldns_wire2str_rrquestion_buf(uint8_t* d, size_t dlen, char* s, size_t slen) { /* use arguments as temporary variables */ - return sldns_wire2str_rrquestion_scan(&d, &dlen, &s, &slen, NULL, 0); + return sldns_wire2str_rrquestion_scan(&d, &dlen, &s, &slen, NULL, 0, NULL); } int sldns_wire2str_rdata_buf(uint8_t* rdata, size_t rdata_len, char* str, @@ -266,13 +267,13 @@ int sldns_wire2str_rdata_buf(uint8_t* rdata, size_t rdata_len, char* str, { /* use arguments as temporary variables */ return sldns_wire2str_rdata_scan(&rdata, &rdata_len, &str, &str_len, - rrtype, NULL, 0); + rrtype, NULL, 0, NULL); } int sldns_wire2str_rr_unknown_buf(uint8_t* d, size_t dlen, char* s, size_t slen) { /* use arguments as temporary variables */ - return sldns_wire2str_rr_unknown_scan(&d, &dlen, &s, &slen, NULL, 0); + return sldns_wire2str_rr_unknown_scan(&d, &dlen, &s, &slen, NULL, 0, NULL); } int sldns_wire2str_rr_comment_buf(uint8_t* rr, size_t rrlen, size_t dname_len, @@ -310,7 +311,7 @@ int sldns_wire2str_opcode_buf(int opcode, char* s, size_t slen) int sldns_wire2str_dname_buf(uint8_t* d, size_t dlen, char* s, size_t slen) { /* use arguments as temporary variables */ - return sldns_wire2str_dname_scan(&d, &dlen, &s, &slen, NULL, 0); + return sldns_wire2str_dname_scan(&d, &dlen, &s, &slen, NULL, 0, NULL); } int sldns_str_vprint(char** str, size_t* slen, const char* format, va_list args) @@ -365,7 +366,7 @@ static int print_remainder_hex(const char* pref, uint8_t** d, size_t* dlen, int sldns_wire2str_pkt_scan(uint8_t** d, size_t* dlen, char** s, size_t* slen) { - int w = 0; + int w = 0, comprloop = 0; unsigned qdcount, ancount, nscount, arcount, i; uint8_t* pkt = *d; size_t pktlen = *dlen; @@ -382,25 +383,25 @@ int sldns_wire2str_pkt_scan(uint8_t** d, size_t* dlen, char** s, size_t* slen) w += sldns_str_print(s, slen, ";; QUESTION SECTION:\n"); for(i=0; i<qdcount; i++) { w += sldns_wire2str_rrquestion_scan(d, dlen, s, slen, - pkt, pktlen); + pkt, pktlen, &comprloop); if(!*dlen) break; } w += sldns_str_print(s, slen, "\n"); w += sldns_str_print(s, slen, ";; ANSWER SECTION:\n"); for(i=0; i<ancount; i++) { - w += sldns_wire2str_rr_scan(d, dlen, s, slen, pkt, pktlen); + w += sldns_wire2str_rr_scan(d, dlen, s, slen, pkt, pktlen, &comprloop); if(!*dlen) break; } w += sldns_str_print(s, slen, "\n"); w += sldns_str_print(s, slen, ";; AUTHORITY SECTION:\n"); for(i=0; i<nscount; i++) { - w += sldns_wire2str_rr_scan(d, dlen, s, slen, pkt, pktlen); + w += sldns_wire2str_rr_scan(d, dlen, s, slen, pkt, pktlen, &comprloop); if(!*dlen) break; } w += sldns_str_print(s, slen, "\n"); w += sldns_str_print(s, slen, ";; ADDITIONAL SECTION:\n"); for(i=0; i<arcount; i++) { - w += sldns_wire2str_rr_scan(d, dlen, s, slen, pkt, pktlen); + w += sldns_wire2str_rr_scan(d, dlen, s, slen, pkt, pktlen, &comprloop); if(!*dlen) break; } /* other fields: WHEN(time), SERVER(IP) not available here. */ @@ -449,7 +450,7 @@ static int sldns_rr_tcttl_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) } int sldns_wire2str_rr_scan(uint8_t** d, size_t* dlen, char** s, size_t* slen, - uint8_t* pkt, size_t pktlen) + uint8_t* pkt, size_t pktlen, int* comprloop) { int w = 0; uint8_t* rr = *d; @@ -464,7 +465,7 @@ int sldns_wire2str_rr_scan(uint8_t** d, size_t* dlen, char** s, size_t* slen, /* try to scan the rdata with pretty-printing, but if that fails, then * scan the rdata as an unknown RR type */ - w += sldns_wire2str_dname_scan(d, dlen, s, slen, pkt, pktlen); + w += sldns_wire2str_dname_scan(d, dlen, s, slen, pkt, pktlen, comprloop); w += sldns_str_print(s, slen, "\t"); dname_off = rrlen-(*dlen); if(*dlen == 4) { @@ -508,7 +509,8 @@ int sldns_wire2str_rr_scan(uint8_t** d, size_t* dlen, char** s, size_t* slen, w += print_remainder_hex(";Error partial rdata 0x", d, dlen, s, slen); return w + sldns_str_print(s, slen, "\n"); } - w += sldns_wire2str_rdata_scan(d, &rdlen, s, slen, rrtype, pkt, pktlen); + w += sldns_wire2str_rdata_scan(d, &rdlen, s, slen, rrtype, pkt, pktlen, + comprloop); (*dlen) -= (ordlen-rdlen); /* default comment */ @@ -519,11 +521,11 @@ int sldns_wire2str_rr_scan(uint8_t** d, size_t* dlen, char** s, size_t* slen, } int sldns_wire2str_rrquestion_scan(uint8_t** d, size_t* dlen, char** s, - size_t* slen, uint8_t* pkt, size_t pktlen) + size_t* slen, uint8_t* pkt, size_t pktlen, int* comprloop) { int w = 0; uint16_t t, c; - w += sldns_wire2str_dname_scan(d, dlen, s, slen, pkt, pktlen); + w += sldns_wire2str_dname_scan(d, dlen, s, slen, pkt, pktlen, comprloop); w += sldns_str_print(s, slen, "\t"); if(*dlen < 4) { if(*dlen == 0) @@ -543,11 +545,11 @@ int sldns_wire2str_rrquestion_scan(uint8_t** d, size_t* dlen, char** s, } int sldns_wire2str_rr_unknown_scan(uint8_t** d, size_t* dlen, char** s, - size_t* slen, uint8_t* pkt, size_t pktlen) + size_t* slen, uint8_t* pkt, size_t pktlen, int* comprloop) { size_t rdlen, ordlen; int w = 0; - w += sldns_wire2str_dname_scan(d, dlen, s, slen, pkt, pktlen); + w += sldns_wire2str_dname_scan(d, dlen, s, slen, pkt, pktlen, comprloop); w += sldns_str_print(s, slen, "\t"); w += sldns_rr_tcttl_scan(d, dlen, s, slen); w += sldns_str_print(s, slen, "\t"); @@ -585,6 +587,7 @@ static int rr_comment_dnskey(char** s, size_t* slen, uint8_t* rr, if(rrlen < dname_off + 10) return 0; rdlen = sldns_read_uint16(rr+dname_off+8); if(rrlen < dname_off + 10 + rdlen) return 0; + if(rdlen < 2) return 0; rdata = rr + dname_off + 10; flags = (int)sldns_read_uint16(rdata); w += sldns_str_print(s, slen, " ;{"); @@ -698,7 +701,8 @@ int sldns_wire2str_header_scan(uint8_t** d, size_t* dlen, char** s, } int sldns_wire2str_rdata_scan(uint8_t** d, size_t* dlen, char** s, - size_t* slen, uint16_t rrtype, uint8_t* pkt, size_t pktlen) + size_t* slen, uint16_t rrtype, uint8_t* pkt, size_t pktlen, + int* comprloop) { /* try to prettyprint, but if that fails, use unknown format */ uint8_t* origd = *d; @@ -724,7 +728,7 @@ int sldns_wire2str_rdata_scan(uint8_t** d, size_t* dlen, char** s, if(r_cnt != 0) w += sldns_str_print(s, slen, " "); n = sldns_wire2str_rdf_scan(d, dlen, s, slen, rdftype, - pkt, pktlen); + pkt, pktlen, comprloop); if(n == -1) { failed: /* failed, use unknown format */ @@ -775,21 +779,27 @@ static int dname_char_print(char** s, size_t* slen, uint8_t c) } int sldns_wire2str_dname_scan(uint8_t** d, size_t* dlen, char** s, size_t* slen, - uint8_t* pkt, size_t pktlen) + uint8_t* pkt, size_t pktlen, int* comprloop) { int w = 0; /* spool labels onto the string, use compression if its there */ uint8_t* pos = *d; unsigned i, counter=0; - const unsigned maxcompr = 1000; /* loop detection, max compr ptrs */ + unsigned maxcompr = MAX_COMPRESS_PTRS; /* loop detection, max compr ptrs */ int in_buf = 1; + if(comprloop) { + if(*comprloop != 0) + maxcompr = 30; /* for like ipv6 reverse name, per label */ + if(*comprloop > 4) + maxcompr = 4; /* just don't want to spend time, any more */ + } if(*dlen == 0) return sldns_str_print(s, slen, "ErrorMissingDname"); if(*pos == 0) { (*d)++; (*dlen)--; return sldns_str_print(s, slen, "."); } - while(*pos) { + while((!pkt || pos < pkt+pktlen) && *pos) { /* read label length */ uint8_t labellen = *pos++; if(in_buf) { (*d)++; (*dlen)--; } @@ -810,9 +820,12 @@ int sldns_wire2str_dname_scan(uint8_t** d, size_t* dlen, char** s, size_t* slen, if(!pkt || target >= pktlen) return w + sldns_str_print(s, slen, "ErrorComprPtrOutOfBounds"); - if(counter++ > maxcompr) + if(counter++ > maxcompr) { + if(comprloop && *comprloop < 10) + (*comprloop)++; return w + sldns_str_print(s, slen, "ErrorComprPtrLooped"); + } in_buf = 0; pos = pkt+target; continue; @@ -928,14 +941,14 @@ int sldns_wire2str_ttl_scan(uint8_t** d, size_t* dlen, char** s, size_t* slen) } int sldns_wire2str_rdf_scan(uint8_t** d, size_t* dlen, char** s, size_t* slen, - int rdftype, uint8_t* pkt, size_t pktlen) + int rdftype, uint8_t* pkt, size_t pktlen, int* comprloop) { if(*dlen == 0) return 0; switch(rdftype) { case LDNS_RDF_TYPE_NONE: return 0; case LDNS_RDF_TYPE_DNAME: - return sldns_wire2str_dname_scan(d, dlen, s, slen, pkt, pktlen); + return sldns_wire2str_dname_scan(d, dlen, s, slen, pkt, pktlen, comprloop); case LDNS_RDF_TYPE_INT8: return sldns_wire2str_int8_scan(d, dlen, s, slen); case LDNS_RDF_TYPE_INT16: @@ -987,7 +1000,7 @@ int sldns_wire2str_rdf_scan(uint8_t** d, size_t* dlen, char** s, size_t* slen, return sldns_wire2str_atma_scan(d, dlen, s, slen); case LDNS_RDF_TYPE_IPSECKEY: return sldns_wire2str_ipseckey_scan(d, dlen, s, slen, pkt, - pktlen); + pktlen, comprloop); case LDNS_RDF_TYPE_HIP: return sldns_wire2str_hip_scan(d, dlen, s, slen); case LDNS_RDF_TYPE_INT16_DATA: @@ -1529,7 +1542,7 @@ int sldns_wire2str_atma_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) /* internal scan routine that can modify arguments on failure */ static int sldns_wire2str_ipseckey_scan_internal(uint8_t** d, size_t* dl, - char** s, size_t* sl, uint8_t* pkt, size_t pktlen) + char** s, size_t* sl, uint8_t* pkt, size_t pktlen, int* comprloop) { /* http://www.ietf.org/internet-drafts/draft-ietf-ipseckey-rr-12.txt*/ uint8_t precedence, gateway_type, algorithm; @@ -1557,7 +1570,7 @@ static int sldns_wire2str_ipseckey_scan_internal(uint8_t** d, size_t* dl, w += sldns_wire2str_aaaa_scan(d, dl, s, sl); break; case 3: /* dname */ - w += sldns_wire2str_dname_scan(d, dl, s, sl, pkt, pktlen); + w += sldns_wire2str_dname_scan(d, dl, s, sl, pkt, pktlen, comprloop); break; default: /* unknown */ return -1; @@ -1571,12 +1584,12 @@ static int sldns_wire2str_ipseckey_scan_internal(uint8_t** d, size_t* dl, } int sldns_wire2str_ipseckey_scan(uint8_t** d, size_t* dl, char** s, size_t* sl, - uint8_t* pkt, size_t pktlen) + uint8_t* pkt, size_t pktlen, int* comprloop) { uint8_t* od = *d; char* os = *s; size_t odl = *dl, osl = *sl; - int w=sldns_wire2str_ipseckey_scan_internal(d, dl, s, sl, pkt, pktlen); + int w=sldns_wire2str_ipseckey_scan_internal(d, dl, s, sl, pkt, pktlen, comprloop); if(w == -1) { *d = od; *s = os; |
